blob: 1cd9159ca67d1420d2af957a8af625a510169f4b [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;
Daniel Veillard01fa6152004-06-29 17:04:39 +00001004 /* Removed, since not used. */
1005 /*
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001006 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
1007 fprintf(output, "mixed_or_elems ");
1008 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00001009 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001010 case XML_SCHEMA_CONTENT_BASIC:
1011 fprintf(output, "basic ");
1012 break;
1013 case XML_SCHEMA_CONTENT_SIMPLE:
1014 fprintf(output, "simple ");
1015 break;
1016 case XML_SCHEMA_CONTENT_ANY:
1017 fprintf(output, "any ");
1018 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00001019 }
1020 fprintf(output, "\n");
1021 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001022 fprintf(output, " ");
1023 if (type->minOccurs != 1)
1024 fprintf(output, "min: %d ", type->minOccurs);
1025 if (type->maxOccurs >= UNBOUNDED)
1026 fprintf(output, "max: unbounded\n");
1027 else if (type->maxOccurs != 1)
1028 fprintf(output, "max: %d\n", type->maxOccurs);
1029 else
1030 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001031 }
1032 if (type->annot != NULL)
1033 xmlSchemaAnnotDump(output, type->annot);
1034 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001035 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00001036
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001037 fprintf(output, " subtypes: ");
1038 while (sub != NULL) {
1039 fprintf(output, "%s ", sub->name);
1040 sub = sub->next;
1041 }
1042 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001043 }
1044
1045}
1046
1047/**
1048 * xmlSchemaDump:
1049 * @output: the file output
1050 * @schema: a schema structure
1051 *
1052 * Dump a Schema structure.
1053 */
1054void
1055xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
1056{
1057 if (schema == NULL) {
1058 fprintf(output, "Schemas: NULL\n");
1059 return;
1060 }
1061 fprintf(output, "Schemas: ");
1062 if (schema->name != NULL)
1063 fprintf(output, "%s, ", schema->name);
1064 else
1065 fprintf(output, "no name, ");
1066 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00001067 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001068 else
1069 fprintf(output, "no target namespace");
1070 fprintf(output, "\n");
1071 if (schema->annot != NULL)
1072 xmlSchemaAnnotDump(output, schema->annot);
1073
1074 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
1075 output);
1076 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001077 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00001078}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001079#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00001080
1081/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001082 * *
1083 * Utilities *
1084 * *
1085 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001086
Daniel Veillard01fa6152004-06-29 17:04:39 +00001087xmlAttrPtr
1088xmlSchemaGetPropNode(xmlNodePtr node, const xmlChar *name)
1089{
1090 xmlAttrPtr prop;
1091
1092 if ((node == NULL) || (name == NULL)) return(NULL);
1093 prop = node->properties;
1094 while (prop != NULL) {
1095 if ((xmlStrEqual(prop->name, name)) &&
1096 (prop->ns == NULL))
1097 return(prop);
1098 prop = prop->next;
1099 }
1100 return (NULL);
1101}
1102
1103static const xmlChar *
1104xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1105{
1106 xmlChar *val;
1107 const xmlChar *ret;
1108
1109 val = xmlNodeGetContent(node);
1110 if (val == NULL)
1111 return(NULL);
1112 ret = xmlDictLookup(ctxt->dict, val, -1);
1113 xmlFree(val);
1114 return(ret);
1115}
1116
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001117/**
1118 * xmlSchemaGetProp:
1119 * @ctxt: the parser context
1120 * @node: the node
1121 * @name: the property name
1122 *
1123 * Read a attribute value and internalize the string
1124 *
1125 * Returns the string or NULL if not present.
1126 */
1127static const xmlChar *
1128xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1129 const char *name)
1130{
1131 xmlChar *val;
1132 const xmlChar *ret;
1133
1134 val = xmlGetProp(node, BAD_CAST name);
1135 if (val == NULL)
1136 return(NULL);
1137 ret = xmlDictLookup(ctxt->dict, val, -1);
1138 xmlFree(val);
1139 return(ret);
1140}
1141
William M. Brack29aa7722004-05-12 00:27:56 +00001142#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001143/**
1144 * xmlSchemaGetNamespace:
1145 * @ctxt: the parser context
1146 * @schema: the schemas containing the declaration
1147 * @node: the node
1148 * @qname: the QName to analyze
1149 *
1150 * Find the namespace name for the given declaration.
1151 *
1152 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00001153 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001154 */
1155static const xmlChar *
1156xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1157 xmlNodePtr node, const xmlChar *qname,
1158 const xmlChar **namespace) {
1159 int len;
1160 const xmlChar *name, *prefix, *def = NULL;
1161 xmlNsPtr ns;
1162
1163 *namespace = NULL;
1164
William M. Bracke7091952004-05-11 15:09:58 +00001165 /* TODO: The following seems to be not correct here:
1166 * 1. The name of a declaration is a NCName, not a QName.
1167 * 2. The attribute "targetNamespace" is allowed for the
1168 * <schema> Element Information Item only.
1169 * 3. One cannot evaluate the target namespace, by the type
1170 * of declaration, since it is dependant on the xxxFormDefault
1171 * of <schema> and the form attribute of an <element> or <attribute>.
1172 */
1173
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001174 if (xmlStrEqual(node->name, BAD_CAST "element") ||
1175 xmlStrEqual(node->name, BAD_CAST "attribute") ||
1176 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
1177 xmlStrEqual(node->name, BAD_CAST "complexType")) {
1178 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
1179 }
1180
William M. Bracke7091952004-05-11 15:09:58 +00001181
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001182 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
1183 name = xmlSplitQName3(qname, &len);
1184 if (name == NULL) {
1185 if (def == NULL) {
1186 if (xmlStrEqual(node->name, BAD_CAST "element")) {
1187 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
1188 *namespace = schema->targetNamespace;
1189 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
1190 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
1191 *namespace = schema->targetNamespace;
1192 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
1193 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
1194 *namespace = schema->targetNamespace;
1195 }
1196 } else {
1197 *namespace = def;
1198 }
1199 return(qname);
1200 }
William M. Bracke7091952004-05-11 15:09:58 +00001201
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001202 name = xmlDictLookup(ctxt->dict, name, -1);
1203 prefix = xmlDictLookup(ctxt->dict, qname, len);
1204 if (def != NULL) {
1205 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
1206 "%s: presence of both prefix %s and targetNamespace\n",
1207 node->name, prefix);
1208 }
1209 ns = xmlSearchNs(node->doc, node, prefix);
1210 if (ns == NULL) {
1211 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
1212 "%s: the QName prefix %s is undefined\n",
1213 node->name, prefix);
1214 return(name);
1215 }
1216 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
1217 return(name);
1218}
William M. Brack29aa7722004-05-12 00:27:56 +00001219#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001220
1221/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00001222 * *
1223 * Parsing functions *
1224 * *
1225 ************************************************************************/
1226
1227/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001228 * xmlSchemaGetElem:
1229 * @schema: the schemas context
1230 * @name: the element name
1231 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00001232 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001233 *
1234 * Lookup a an element in the schemas or the accessible schemas
1235 *
1236 * Returns the element definition or NULL if not found.
1237 */
1238static xmlSchemaElementPtr
1239xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00001240 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001241{
1242 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00001243 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001244
1245 if ((name == NULL) || (schema == NULL))
1246 return (NULL);
1247
Daniel Veillard3646d642004-06-02 19:19:14 +00001248
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001249 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001250 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00001251 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001252 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001253 } else
1254 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00001255 /*
1256 * This one was removed, since top level element declarations have
1257 * the target namespace specified in targetNamespace of the <schema>
1258 * information element, even if elementFormDefault is "unqualified".
1259 */
1260
1261 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001262 if (xmlStrEqual(namespace, schema->targetNamespace))
1263 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
1264 else
1265 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001266 if ((ret != NULL) &&
1267 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001268 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00001269 }
William M. Bracke7091952004-05-11 15:09:58 +00001270 */
Daniel Veillard3646d642004-06-02 19:19:14 +00001271
1272 /* if (level > 0) */
1273 if (namespace == NULL)
1274 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1275 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001276 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001277 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00001278 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00001279 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
1280 return (ret);
1281 } else
1282 ret = NULL;
1283 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001284#ifdef DEBUG
1285 if (ret == NULL) {
1286 if (namespace == NULL)
1287 fprintf(stderr, "Unable to lookup type %s", name);
1288 else
1289 fprintf(stderr, "Unable to lookup type %s:%s", name,
1290 namespace);
1291 }
1292#endif
1293 return (ret);
1294}
1295
1296/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001297 * xmlSchemaGetType:
1298 * @schema: the schemas context
1299 * @name: the type name
1300 * @ns: the type namespace
1301 *
1302 * Lookup a type in the schemas or the predefined types
1303 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001304 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00001305 */
1306static xmlSchemaTypePtr
1307xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001308 const xmlChar * namespace)
1309{
Daniel Veillard4255d502002-04-16 15:50:10 +00001310 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00001311 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00001312
1313 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001314 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001315 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001316 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001317 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001318 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001319 }
1320 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00001321 if (ret != NULL)
1322 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00001323 if (namespace == NULL)
1324 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1325 else
Daniel Veillard1d913862003-11-21 00:28:39 +00001326 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001327 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00001328 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00001329 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1330 return (ret);
1331 } else
1332 ret = NULL;
1333 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001334#ifdef DEBUG
1335 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001336 if (namespace == NULL)
1337 fprintf(stderr, "Unable to lookup type %s", name);
1338 else
1339 fprintf(stderr, "Unable to lookup type %s:%s", name,
1340 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00001341 }
1342#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001343 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001344}
1345
Daniel Veillard3646d642004-06-02 19:19:14 +00001346/**
1347 * xmlSchemaGetAttribute:
1348 * @schema: the context of the schema
1349 * @name: the name of the attribute
1350 * @ns: the target namespace of the attribute
1351 *
1352 * Lookup a an attribute in the schema or imported schemas
1353 *
1354 * Returns the attribute declaration or NULL if not found.
1355 */
1356static xmlSchemaAttributePtr
1357xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
1358 const xmlChar * namespace)
1359{
1360 xmlSchemaAttributePtr ret;
1361 xmlSchemaImportPtr import = NULL;
1362
1363 if ((name == NULL) || (schema == NULL))
1364 return (NULL);
1365
1366
1367 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
1368 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
1369 return (ret);
1370 else
1371 ret = NULL;
1372 if (namespace == NULL)
1373 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1374 else
1375 import = xmlHashLookup(schema->schemasImports, namespace);
1376 if (import != NULL) {
1377 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
1378 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
1379 return (ret);
1380 } else
1381 ret = NULL;
1382 }
1383#ifdef DEBUG
1384 if (ret == NULL) {
1385 if (namespace == NULL)
1386 fprintf(stderr, "Unable to lookup attribute %s", name);
1387 else
1388 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
1389 namespace);
1390 }
1391#endif
1392 return (ret);
1393}
1394
1395/**
1396 * xmlSchemaGetAttributeGroup:
1397 * @schema: the context of the schema
1398 * @name: the name of the attribute group
1399 * @ns: the target namespace of the attribute group
1400 *
1401 * Lookup a an attribute group in the schema or imported schemas
1402 *
1403 * Returns the attribute group definition or NULL if not found.
1404 */
1405static xmlSchemaAttributeGroupPtr
1406xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
1407 const xmlChar * namespace)
1408{
1409 xmlSchemaAttributeGroupPtr ret;
1410 xmlSchemaImportPtr import = NULL;
1411
1412 if ((name == NULL) || (schema == NULL))
1413 return (NULL);
1414
1415
1416 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
1417 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1418 return (ret);
1419 else
1420 ret = NULL;
1421 if (namespace == NULL)
1422 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1423 else
1424 import = xmlHashLookup(schema->schemasImports, namespace);
1425 if (import != NULL) {
1426 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
1427 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
1428 return (ret);
1429 else
1430 ret = NULL;
1431 }
1432#ifdef DEBUG
1433 if (ret == NULL) {
1434 if (namespace == NULL)
1435 fprintf(stderr, "Unable to lookup attribute group %s", name);
1436 else
1437 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
1438 namespace);
1439 }
1440#endif
1441 return (ret);
1442}
1443
1444/**
1445 * xmlSchemaGetGroup:
1446 * @schema: the context of the schema
1447 * @name: the name of the group
1448 * @ns: the target namespace of the group
1449 *
1450 * Lookup a group in the schema or imported schemas
1451 *
1452 * Returns the group definition or NULL if not found.
1453 */
1454static xmlSchemaTypePtr
1455xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
1456 const xmlChar * namespace)
1457{
1458 xmlSchemaTypePtr ret;
1459 xmlSchemaImportPtr import = NULL;
1460
1461 if ((name == NULL) || (schema == NULL))
1462 return (NULL);
1463
1464
1465 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
1466 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1467 return (ret);
1468 else
1469 ret = NULL;
1470 if (namespace == NULL)
1471 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
1472 else
1473 import = xmlHashLookup(schema->schemasImports, namespace);
1474 if (import != NULL) {
1475 ret = xmlSchemaGetGroup(import->schema, name, namespace);
1476 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
1477 return (ret);
1478 else
1479 ret = NULL;
1480 }
1481#ifdef DEBUG
1482 if (ret == NULL) {
1483 if (namespace == NULL)
1484 fprintf(stderr, "Unable to lookup group %s", name);
1485 else
1486 fprintf(stderr, "Unable to lookup group %s:%s", name,
1487 namespace);
1488 }
1489#endif
1490 return (ret);
1491}
1492
Daniel Veillard4255d502002-04-16 15:50:10 +00001493/************************************************************************
1494 * *
1495 * Parsing functions *
1496 * *
1497 ************************************************************************/
1498
1499#define IS_BLANK_NODE(n) \
1500 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
1501
1502/**
1503 * xmlSchemaIsBlank:
1504 * @str: a string
1505 *
1506 * Check if a string is ignorable
1507 *
1508 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
1509 */
1510static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001511xmlSchemaIsBlank(xmlChar * str)
1512{
Daniel Veillard4255d502002-04-16 15:50:10 +00001513 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001514 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00001516 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001517 return (0);
1518 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00001519 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001520 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001521}
1522
1523/**
1524 * xmlSchemaAddNotation:
1525 * @ctxt: a schema validation context
1526 * @schema: the schema being built
1527 * @name: the item name
1528 *
1529 * Add an XML schema Attrribute declaration
1530 * *WARNING* this interface is highly subject to change
1531 *
1532 * Returns the new struture or NULL in case of error
1533 */
1534static xmlSchemaNotationPtr
1535xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001536 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001537{
1538 xmlSchemaNotationPtr ret = NULL;
1539 int val;
1540
1541 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1542 return (NULL);
1543
1544 if (schema->notaDecl == NULL)
1545 schema->notaDecl = xmlHashCreate(10);
1546 if (schema->notaDecl == NULL)
1547 return (NULL);
1548
1549 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
1550 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001551 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001552 return (NULL);
1553 }
1554 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001555 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001556 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
1557 ret);
1558 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001559 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1560 XML_SCHEMAP_REDEFINED_NOTATION,
1561 "Notation %s already defined\n",
1562 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001563 xmlFree(ret);
1564 return (NULL);
1565 }
1566 return (ret);
1567}
1568
1569
1570/**
1571 * xmlSchemaAddAttribute:
1572 * @ctxt: a schema validation context
1573 * @schema: the schema being built
1574 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001575 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001576 *
1577 * Add an XML schema Attrribute declaration
1578 * *WARNING* this interface is highly subject to change
1579 *
1580 * Returns the new struture or NULL in case of error
1581 */
1582static xmlSchemaAttributePtr
1583xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001584 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001585{
1586 xmlSchemaAttributePtr ret = NULL;
1587 int val;
1588
1589 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1590 return (NULL);
1591
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001592#ifdef DEBUG
1593 fprintf(stderr, "Adding attribute %s\n", name);
1594 if (namespace != NULL)
1595 fprintf(stderr, " target namespace %s\n", namespace);
1596#endif
1597
Daniel Veillard4255d502002-04-16 15:50:10 +00001598 if (schema->attrDecl == NULL)
1599 schema->attrDecl = xmlHashCreate(10);
1600 if (schema->attrDecl == NULL)
1601 return (NULL);
1602
1603 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
1604 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001605 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001606 return (NULL);
1607 }
1608 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001609 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1610 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001611 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001612 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001613 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1615 XML_SCHEMAP_REDEFINED_ATTR,
1616 "Attribute %s already defined\n",
1617 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001618 xmlFree(ret);
1619 return (NULL);
1620 }
1621 return (ret);
1622}
1623
1624/**
1625 * xmlSchemaAddAttributeGroup:
1626 * @ctxt: a schema validation context
1627 * @schema: the schema being built
1628 * @name: the item name
1629 *
1630 * Add an XML schema Attrribute Group declaration
1631 *
1632 * Returns the new struture or NULL in case of error
1633 */
1634static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001635xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
1636 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00001637{
1638 xmlSchemaAttributeGroupPtr ret = NULL;
1639 int val;
1640
1641 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1642 return (NULL);
1643
1644 if (schema->attrgrpDecl == NULL)
1645 schema->attrgrpDecl = xmlHashCreate(10);
1646 if (schema->attrgrpDecl == NULL)
1647 return (NULL);
1648
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001649 ret =
1650 (xmlSchemaAttributeGroupPtr)
1651 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00001652 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001653 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001654 return (NULL);
1655 }
1656 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001657 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001658 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001659 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001660 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001661 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1662 XML_SCHEMAP_REDEFINED_ATTRGROUP,
1663 "Attribute group %s already defined\n",
1664 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001665 xmlFree(ret);
1666 return (NULL);
1667 }
1668 return (ret);
1669}
1670
1671/**
1672 * xmlSchemaAddElement:
1673 * @ctxt: a schema validation context
1674 * @schema: the schema being built
1675 * @name: the type name
1676 * @namespace: the type namespace
1677 *
1678 * Add an XML schema Element declaration
1679 * *WARNING* this interface is highly subject to change
1680 *
1681 * Returns the new struture or NULL in case of error
1682 */
1683static xmlSchemaElementPtr
1684xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1685 const xmlChar * name, const xmlChar * namespace)
1686{
1687 xmlSchemaElementPtr ret = NULL;
1688 int val;
1689
1690 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1691 return (NULL);
1692
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001693#ifdef DEBUG
1694 fprintf(stderr, "Adding element %s\n", name);
1695 if (namespace != NULL)
1696 fprintf(stderr, " target namespace %s\n", namespace);
1697#endif
1698
Daniel Veillard4255d502002-04-16 15:50:10 +00001699 if (schema->elemDecl == NULL)
1700 schema->elemDecl = xmlHashCreate(10);
1701 if (schema->elemDecl == NULL)
1702 return (NULL);
1703
1704 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
1705 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001706 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001707 return (NULL);
1708 }
1709 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001710 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1711 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00001712 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001713 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001714 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001715 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00001716
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001717 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001718 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
1719 namespace, ret);
1720 if (val != 0) {
1721 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1722 XML_SCHEMAP_REDEFINED_ELEMENT,
1723 "Element %s already defined\n",
1724 name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001725 xmlFree(ret);
1726 return (NULL);
1727 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001728 }
1729 return (ret);
1730}
1731
1732/**
1733 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001734 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00001735 * @schema: the schema being built
1736 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001737 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00001738 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001739 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00001740 * *WARNING* this interface is highly subject to change
1741 *
1742 * Returns the new struture or NULL in case of error
1743 */
1744static xmlSchemaTypePtr
1745xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001746 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00001747{
1748 xmlSchemaTypePtr ret = NULL;
1749 int val;
1750
1751 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1752 return (NULL);
1753
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001754#ifdef DEBUG
1755 fprintf(stderr, "Adding type %s\n", name);
1756 if (namespace != NULL)
1757 fprintf(stderr, " target namespace %s\n", namespace);
1758#endif
1759
Daniel Veillard4255d502002-04-16 15:50:10 +00001760 if (schema->typeDecl == NULL)
1761 schema->typeDecl = xmlHashCreate(10);
1762 if (schema->typeDecl == NULL)
1763 return (NULL);
1764
1765 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1766 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001767 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001768 return (NULL);
1769 }
1770 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001771 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001772 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001773 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00001774 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001775 if (ctxt->includes == 0) {
1776 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1777 XML_SCHEMAP_REDEFINED_TYPE,
1778 "Type %s already defined\n",
1779 name, NULL);
1780 xmlFree(ret);
1781 return (NULL);
1782 } else {
1783 xmlSchemaTypePtr prev;
1784
1785 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
1786 if (prev == NULL) {
1787 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
1788 XML_ERR_INTERNAL_ERROR,
1789 "Internal error on type %s definition\n",
1790 name, NULL);
1791 xmlFree(ret);
1792 return (NULL);
1793 }
1794 ret->redef = prev->redef;
1795 prev->redef = ret;
1796 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001797 }
1798 ret->minOccurs = 1;
1799 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00001800 ret->attributeUses = NULL;
1801 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001802
1803 return (ret);
1804}
1805
1806/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00001807 * xmlSchemaNewItemInternal:
1808 * @ctxt: the schema parser context
1809 * @name: the internal name of the restriction
1810 *
1811 * Createa an schema item
1812 *
1813 * Returns the new structure or NULL in case of an error.
1814 */
1815static xmlSchemaTypePtr
1816xmlSchemaNewItemInternal(xmlSchemaParserCtxtPtr ctxt,
1817 const xmlChar * name)
1818{
1819 xmlSchemaTypePtr ret = NULL;
1820
1821 if ((ctxt == NULL) || (name == NULL))
1822 return (NULL);
1823
1824#ifdef DEBUG
1825 fprintf(stderr, "Creating item %s\n", name);
1826#endif
1827 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1828 if (ret == NULL) {
1829 xmlSchemaPErrMemory(ctxt, "allocating item", NULL);
1830 return (NULL);
1831 }
1832 memset(ret, 0, sizeof(xmlSchemaType));
1833 ret->name = xmlDictLookup(ctxt->dict, name, -1);
1834 ret->minOccurs = 1;
1835 ret->maxOccurs = 1;
1836
1837 return (ret);
1838}
1839
1840/**
1841 * xmlSchemaNewRestriction:
1842 * @ctxt: the schema parser context
1843 * @name: the internal name of the restriction
1844 *
1845 * Create a <restriction> item
1846 *
1847 * Returns the new structure or NULL in case of an error.
1848 */
1849static xmlSchemaTypePtr
1850xmlSchemaNewRestriction(xmlSchemaParserCtxtPtr ctxt,
1851 const xmlChar * name)
1852{
1853 xmlSchemaTypePtr ret;
1854
1855 ret = xmlSchemaNewItemInternal(ctxt, name);
1856 if (ret != NULL)
1857 ret->type = XML_SCHEMA_TYPE_RESTRICTION;
1858
1859 return (ret);
1860}
1861
1862/**
1863 * xmlSchemaNewExtension:
1864 * @ctxt: the schema parser context
1865 * @name: the internal name of the extension
1866 *
1867 * Create an <extension> item
1868 *
1869 * Returns the new structure or NULL in case of an error.
1870 */
1871static xmlSchemaTypePtr
1872xmlSchemaNewExtension(xmlSchemaParserCtxtPtr ctxt,
1873 const xmlChar * name)
1874{
1875 xmlSchemaTypePtr ret;
1876
1877 ret = xmlSchemaNewItemInternal(ctxt, name);
1878 if (ret != NULL)
1879 ret->type = XML_SCHEMA_TYPE_EXTENSION;
1880
1881 return (ret);
1882}
1883
1884/**
1885 * xmlSchemaNewSimpleContent:
1886 * @ctxt: the schema parser context
1887 * @name: the internal name of the simpleContent
1888 *
1889 * Create a <simpleContent> item
1890 *
1891 * Returns the new structure or NULL in case of an error.
1892 */
1893static xmlSchemaTypePtr
1894xmlSchemaNewSimpleContent(xmlSchemaParserCtxtPtr ctxt,
1895 const xmlChar * name)
1896{
1897 xmlSchemaTypePtr ret;
1898
1899 ret = xmlSchemaNewItemInternal(ctxt, name);
1900 if (ret != NULL)
1901 ret->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
1902
1903 return (ret);
1904}
1905
1906/**
1907 * xmlSchemaNewComplexContent:
1908 * @ctxt: the schema parser context
1909 * @name: the internal name of the complexContent
1910 *
1911 * Create a <complexContent> item
1912 *
1913 * Returns the new structure or NULL in case of an error.
1914 */
1915static xmlSchemaTypePtr
1916xmlSchemaNewComplexContent(xmlSchemaParserCtxtPtr ctxt,
1917 const xmlChar * name)
1918{
1919 xmlSchemaTypePtr ret;
1920
1921 ret = xmlSchemaNewItemInternal(ctxt, name);
1922 if (ret != NULL)
1923 ret->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
1924
1925 return (ret);
1926}
1927
1928/**
1929 * xmlSchemaNewUnion:
1930 * @ctxt: the schema parser context
1931 * @name: the internal name of the union
1932 *
1933 * Create an <union> item
1934 * *WARNING* this interface is highly subject to change
1935 *
1936 * Returns the new structure or NULL in case of an error.
1937 */
1938static xmlSchemaTypePtr
1939xmlSchemaNewUnion(xmlSchemaParserCtxtPtr ctxt,
1940 const xmlChar * name)
1941{
1942 xmlSchemaTypePtr ret;
1943
1944 ret = xmlSchemaNewItemInternal(ctxt, name);
1945 if (ret != NULL)
1946 ret->type = XML_SCHEMA_TYPE_UNION;
1947
1948 return (ret);
1949}
1950
1951/**
1952 * xmlSchemaNewList:
1953 * @ctxt: the schema parser context
1954 * @name: the internal name of the union
1955 *
1956 * Create an <union> item
1957 * *WARNING* this interface is highly subject to change
1958 *
1959 * Returns the new structure or NULL in case of an error.
1960 */
1961static xmlSchemaTypePtr
1962xmlSchemaNewList(xmlSchemaParserCtxtPtr ctxt,
1963 const xmlChar * name)
1964{
1965 xmlSchemaTypePtr ret;
1966
1967 ret = xmlSchemaNewItemInternal(ctxt, name);
1968 if (ret != NULL)
1969 ret->type = XML_SCHEMA_TYPE_LIST;
1970
1971 return (ret);
1972}
1973
1974/**
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001975 * xmlSchemaAddGroup:
1976 * @ctxt: a schema validation context
1977 * @schema: the schema being built
1978 * @name: the group name
1979 *
1980 * Add an XML schema Group definition
1981 *
1982 * Returns the new struture or NULL in case of error
1983 */
1984static xmlSchemaTypePtr
1985xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001986 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001987{
1988 xmlSchemaTypePtr ret = NULL;
1989 int val;
1990
1991 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
1992 return (NULL);
1993
1994 if (schema->groupDecl == NULL)
1995 schema->groupDecl = xmlHashCreate(10);
1996 if (schema->groupDecl == NULL)
1997 return (NULL);
1998
1999 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
2000 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002001 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002002 return (NULL);
2003 }
2004 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002005 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002006 val =
2007 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
2008 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002009 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002010 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2011 XML_SCHEMAP_REDEFINED_GROUP,
2012 "Group %s already defined\n",
2013 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002014 xmlFree(ret);
2015 return (NULL);
2016 }
2017 ret->minOccurs = 1;
2018 ret->maxOccurs = 1;
2019
2020 return (ret);
2021}
2022
Daniel Veillard3646d642004-06-02 19:19:14 +00002023/**
2024 * xmlSchemaNewWildcardNs:
2025 * @ctxt: a schema validation context
2026 *
2027 * Creates a new wildcard namespace constraint.
2028 *
2029 * Returns the new struture or NULL in case of error
2030 */
2031static xmlSchemaWildcardNsPtr
2032xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
2033{
2034 xmlSchemaWildcardNsPtr ret;
2035
2036 ret = (xmlSchemaWildcardNsPtr)
2037 xmlMalloc(sizeof(xmlSchemaWildcardNs));
2038 if (ret == NULL) {
2039 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
2040 return (NULL);
2041 }
2042 ret->value = NULL;
2043 ret->next = NULL;
2044 return (ret);
2045}
2046
2047/**
2048 * xmlSchemaAddWildcard:
2049 * @ctxt: a schema validation context
2050 * @schema: the schema being built
2051 * @name: the group name
2052 *
2053 * Add an XML schema Group definition
2054 *
2055 * Returns the new struture or NULL in case of error
2056 */
2057static xmlSchemaWildcardPtr
2058xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
2059{
2060 xmlSchemaWildcardPtr ret = NULL;
2061
2062 if (ctxt == NULL)
2063 return (NULL);
2064
2065 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
2066 if (ret == NULL) {
2067 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
2068 return (NULL);
2069 }
2070 memset(ret, 0, sizeof(xmlSchemaWildcard));
2071 ret->minOccurs = 1;
2072 ret->maxOccurs = 1;
2073
2074 return (ret);
2075}
2076
Daniel Veillard4255d502002-04-16 15:50:10 +00002077/************************************************************************
2078 * *
2079 * Utilities for parsing *
2080 * *
2081 ************************************************************************/
2082
2083/**
2084 * xmlGetQNameProp:
2085 * @ctxt: a schema validation context
2086 * @node: a subtree containing XML Schema informations
2087 * @name: the attribute name
2088 * @namespace: the result namespace if any
2089 *
2090 * Extract a QName Attribute value
2091 *
2092 * Returns the NCName or NULL if not found, and also update @namespace
2093 * with the namespace URI
2094 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002095static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00002096xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002097 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002098{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002099 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00002100 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002101 const xmlChar *ret, *prefix;
2102 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00002103
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002104 *namespace = NULL;
2105 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002106 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002107 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002108
Daniel Veillardba0153a2004-04-01 10:42:31 +00002109 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00002110 ns = xmlSearchNs(node->doc, node, 0);
2111 if (ns) {
2112 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2113 return (val);
2114 }
2115 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002116 ret = xmlSplitQName3(val, &len);
2117 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002118 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002119 }
2120 ret = xmlDictLookup(ctxt->dict, ret, -1);
2121 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00002122
2123 ns = xmlSearchNs(node->doc, node, prefix);
2124 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002125 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillard01fa6152004-06-29 17:04:39 +00002126 "Attribute \"%s\": the QName prefix \"%s\" is undefined\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002127 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00002128 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002129 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002130 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002131 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002132}
2133
2134/**
2135 * xmlGetMaxOccurs:
2136 * @ctxt: a schema validation context
2137 * @node: a subtree containing XML Schema informations
2138 *
2139 * Get the maxOccurs property
2140 *
2141 * Returns the default if not found, or the value
2142 */
2143static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002144xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2145{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002146 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00002147 int ret = 0;
2148
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002149 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00002150 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002151 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002152
2153 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002154 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00002155 }
2156
2157 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00002158 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002159 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002160 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002161 ret = ret * 10 + (*cur - '0');
2162 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002163 }
William M. Brack76e95df2003-10-18 16:20:14 +00002164 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002165 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002167 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
2168 "invalid value for maxOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002169 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002170 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002171 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002172}
2173
2174/**
2175 * xmlGetMinOccurs:
2176 * @ctxt: a schema validation context
2177 * @node: a subtree containing XML Schema informations
2178 *
2179 * Get the minOccurs property
2180 *
2181 * Returns the default if not found, or the value
2182 */
2183static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002184xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2185{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002186 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00002187 int ret = 0;
2188
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002189 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00002190 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002191 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002192
2193 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00002194 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002195 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002196 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002197 ret = ret * 10 + (*cur - '0');
2198 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002199 }
William M. Brack76e95df2003-10-18 16:20:14 +00002200 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002201 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002202 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002203 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
2204 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002205 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002206 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002207 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002208}
2209
2210/**
2211 * xmlGetBooleanProp:
2212 * @ctxt: a schema validation context
2213 * @node: a subtree containing XML Schema informations
2214 * @name: the attribute name
2215 * @def: the default value
2216 *
2217 * Get is a bolean property is set
2218 *
2219 * Returns the default if not found, 0 if found to be false,
2220 * 1 if found to be true
2221 */
2222static int
2223xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002224 const char *name, int def)
2225{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002226 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00002227
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002228 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002229 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002230 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002232 if (xmlStrEqual(val, BAD_CAST "true"))
2233 def = 1;
2234 else if (xmlStrEqual(val, BAD_CAST "false"))
2235 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00002236 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002237 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_BOOLEAN,
2238 "Attribute %s: the value %s is not boolean\n",
2239 (const xmlChar *) name, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002240 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00002242}
2243
2244/************************************************************************
2245 * *
2246 * Shema extraction from an Infoset *
2247 * *
2248 ************************************************************************/
2249static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
2250 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002251 xmlNodePtr node,
2252 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
2254 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002255 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00002256 xmlNodePtr node,
2257 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002258static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
2259 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00002260 xmlSchemaPtr schema,
2261 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002262 int simple);
Daniel Veillard4255d502002-04-16 15:50:10 +00002263static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
2264 xmlSchemaPtr schema,
2265 xmlNodePtr node);
2266static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
2267 xmlSchemaPtr schema,
2268 xmlNodePtr node);
2269static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
2270 ctxt,
2271 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002272 xmlNodePtr node,
2273 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002274static xmlSchemaAttributeGroupPtr
2275xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00002276 xmlSchemaPtr schema, xmlNodePtr node,
2277 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002278static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
2279 xmlSchemaPtr schema,
2280 xmlNodePtr node);
2281static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
2282 xmlSchemaPtr schema,
2283 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00002284static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002285xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2286 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002287
2288/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002289 * xmlSchemaParseSchemaAttrValue:
2290 *
2291 * @ctxt: a schema parser context
2292 * @attr: the schema attribute being validated
2293 * @type: the built-in type to be validated against
2294 * @value: the value to be validated
2295 *
2296 * Validates a value against the given built-in type.
2297 * This one is intended to be used internally for validation
2298 * of schema attribute values during parsing of the schema.
2299 *
2300 * Returns 0 if the value is valid, a positive error code
2301 * number otherwise and -1 in case of an internal or API error.
2302 */
2303static int
2304xmlSchemaParseSchemaAttrValue(xmlSchemaParserCtxtPtr ctxt,
2305 xmlAttrPtr attr,
2306 xmlSchemaTypePtr type)
2307{
2308 const xmlChar *value;
2309 int ret;
2310
2311 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
2312 return (-1);
2313 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
2314 switch (type->builtInType) {
2315 case XML_SCHEMAS_NCNAME:
2316 ret = xmlValidateNCName(value, 1);
2317 break;
2318 case XML_SCHEMAS_QNAME:
2319 ret = xmlValidateQName(value, 1);
2320 if ((ret == 0) && (attr != NULL)) {
2321 xmlChar *uri = NULL;
2322 xmlChar *local = NULL;
2323 xmlChar *prefix;
2324
2325 local = xmlSplitQName2(value, &prefix);
2326 if (prefix != NULL) {
2327 xmlNsPtr ns;
2328
2329 ns = xmlSearchNs(attr->doc, (xmlNodePtr) attr, prefix);
2330 if (ns == NULL) {
2331 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2332 XML_SCHEMAP_PREFIX_UNDEFINED,
2333 "Attribute \"%s\": the QName prefix "
2334 "\"%s\" is undefined.\n",
2335 attr->name, prefix);
2336 ret = 1;
2337 }
2338 }
2339 if (local != NULL)
2340 xmlFree(local);
2341 if (prefix != NULL)
2342 xmlFree(prefix);
2343 }
2344 break;
2345 default: {
2346 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
2347 XML_SCHEMAS_ERR_INTERNAL,
2348 "Internal error: xmlSchemaParseSchemaAttrValue, validation "
2349 "using this type in not implemented yet\"%s\".\n",
2350 type->name, NULL);
2351 return (-1);
2352 }
2353 }
2354 if (ret > 0) {
2355 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
2356 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2357 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
2358 NULL, NULL, NULL,
2359 "The schema attribute \"%s\" with the value \"%s\" is not "
2360 "of built-in list simple type \"%s\".\n",
2361 attr->name, value, type->name, NULL, NULL);
2362 } else {
2363 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) {
2364 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2365 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2366 NULL, NULL, NULL,
2367 "The schema attribute \"%s\" with the value \"%s\" is not "
2368 "of built-in primitive type \"%s\".\n",
2369 attr->name, value, type->name, NULL, NULL);
2370 } else {
2371 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr,
2372 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
2373 NULL, NULL, NULL,
2374 "The schema attribute \"%s\" with the value \"%s\" is not "
2375 "of built-in atomic simple type \"%s\".\n",
2376 attr->name, value, type->name, NULL, NULL);
2377 }
2378 }
2379 }
2380 return (ret);
2381}
2382
2383/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002384 * xmlSchemaParseAttrDecls:
2385 * @ctxt: a schema validation context
2386 * @schema: the schema being built
2387 * @node: a subtree containing XML Schema informations
2388 * @type: the hosting type
2389 *
2390 * parse a XML schema attrDecls declaration corresponding to
2391 * <!ENTITY % attrDecls
2392 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
2393 */
2394static xmlNodePtr
2395xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2396 xmlNodePtr child, xmlSchemaTypePtr type)
2397{
2398 xmlSchemaAttributePtr lastattr, attr;
2399
2400 lastattr = NULL;
2401 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002402 (IS_SCHEMA(child, "attributeGroup"))) {
2403 attr = NULL;
2404 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00002405 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002406 } else if (IS_SCHEMA(child, "attributeGroup")) {
2407 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00002408 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002409 }
2410 if (attr != NULL) {
2411 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002412 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2413 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
2414 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002415 type->attributes = attr;
2416 lastattr = attr;
2417 } else {
2418 lastattr->next = attr;
2419 lastattr = attr;
2420 }
2421 }
2422 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002423 }
2424 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002425 xmlSchemaWildcardPtr wildcard;
2426
2427 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
2428 if (wildcard != NULL) {
2429 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
2430 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
2431 else
2432 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002433 }
2434 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002435 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002436 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00002437}
2438
2439/**
2440 * xmlSchemaParseAnnotation:
2441 * @ctxt: a schema validation context
2442 * @schema: the schema being built
2443 * @node: a subtree containing XML Schema informations
2444 *
2445 * parse a XML schema Attrribute declaration
2446 * *WARNING* this interface is highly subject to change
2447 *
William M. Bracke7091952004-05-11 15:09:58 +00002448 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00002449 * 1 in case of success.
2450 */
2451static xmlSchemaAnnotPtr
2452xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2453 xmlNodePtr node)
2454{
2455 xmlSchemaAnnotPtr ret;
2456
2457 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2458 return (NULL);
2459 ret = xmlSchemaNewAnnot(ctxt, node);
2460
2461 return (ret);
2462}
2463
2464/**
2465 * xmlSchemaParseFacet:
2466 * @ctxt: a schema validation context
2467 * @schema: the schema being built
2468 * @node: a subtree containing XML Schema informations
2469 *
2470 * parse a XML schema Facet declaration
2471 * *WARNING* this interface is highly subject to change
2472 *
2473 * Returns the new type structure or NULL in case of error
2474 */
2475static xmlSchemaFacetPtr
2476xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002477 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002478{
2479 xmlSchemaFacetPtr facet;
2480 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002481 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00002482
2483 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2484 return (NULL);
2485
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002486 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002487 if (facet == NULL) {
2488 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
2489 return (NULL);
2490 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002491 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002492 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00002493 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002494 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
2495 "Facet %s has no value\n", node->name, NULL);
2496 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00002497 return (NULL);
2498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002499 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002500 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002501 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002502 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002503 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002504 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002505 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002506 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002507 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002508 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002509 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002511 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002513 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002514 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002515 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002516 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002517 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002518 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002519 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002520 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2521 } else if (IS_SCHEMA(node, "minLength")) {
2522 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2523 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002524 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
2525 "Unknown facet type %s\n", node->name, NULL);
2526 xmlSchemaFreeFacet(facet);
2527 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002528 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002529 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00002530 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00002531 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
2532 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
2533 const xmlChar *fixed;
2534
2535 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
2536 if (fixed != NULL) {
2537 if (xmlStrEqual(fixed, BAD_CAST "true"))
2538 facet->fixed = 1;
2539 }
2540 }
2541
Daniel Veillard4255d502002-04-16 15:50:10 +00002542 child = node->children;
2543
2544 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002545 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2546 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002547 }
2548 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002549 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
2550 "Facet %s has unexpected child content\n",
2551 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 }
2553 return (facet);
2554}
2555
2556/**
2557 * xmlSchemaParseAny:
2558 * @ctxt: a schema validation context
2559 * @schema: the schema being built
2560 * @node: a subtree containing XML Schema informations
2561 *
2562 * parse a XML schema Any declaration
2563 * *WARNING* this interface is highly subject to change
2564 *
2565 * Returns the new type structure or NULL in case of error
2566 */
2567static xmlSchemaTypePtr
2568xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2569 xmlNodePtr node)
2570{
2571 xmlSchemaTypePtr type;
2572 xmlNodePtr child = NULL;
2573 xmlChar name[30];
2574
2575 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2576 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002577 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002578 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002579 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002580 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002581 type->node = node;
2582 type->type = XML_SCHEMA_TYPE_ANY;
2583 child = node->children;
2584 type->minOccurs = xmlGetMinOccurs(ctxt, node);
2585 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
2586
2587 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002588 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2589 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002590 }
2591 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002592 xmlSchemaPErr2(ctxt, node, child,
2593 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
2594 "Sequence %s has unexpected content\n", type->name,
2595 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002596 }
2597
2598 return (type);
2599}
2600
2601/**
2602 * xmlSchemaParseNotation:
2603 * @ctxt: a schema validation context
2604 * @schema: the schema being built
2605 * @node: a subtree containing XML Schema informations
2606 *
2607 * parse a XML schema Notation declaration
2608 *
2609 * Returns the new structure or NULL in case of error
2610 */
2611static xmlSchemaNotationPtr
2612xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002613 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002614{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002615 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 xmlSchemaNotationPtr ret;
2617 xmlNodePtr child = NULL;
2618
2619 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2620 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002621 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002623 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
2624 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002625 return (NULL);
2626 }
2627 ret = xmlSchemaAddNotation(ctxt, schema, name);
2628 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002629 return (NULL);
2630 }
2631 child = node->children;
2632 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002633 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2634 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 }
2636 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002637 xmlSchemaPErr2(ctxt, node, child,
2638 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
2639 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002640 }
2641
2642 return (ret);
2643}
2644
2645/**
2646 * xmlSchemaParseAnyAttribute:
2647 * @ctxt: a schema validation context
2648 * @schema: the schema being built
2649 * @node: a subtree containing XML Schema informations
2650 *
2651 * parse a XML schema AnyAttrribute declaration
2652 * *WARNING* this interface is highly subject to change
2653 *
2654 * Returns an attribute def structure or NULL
2655 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002656static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
2658 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002659{
Daniel Veillard3646d642004-06-02 19:19:14 +00002660 const xmlChar *processContents, *nsConstraint, *end, *cur, *dictMember;
2661 xmlChar *member;
2662 xmlSchemaWildcardPtr ret;
2663 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00002665
2666 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2667 return (NULL);
2668
Daniel Veillard3646d642004-06-02 19:19:14 +00002669 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 if (ret == NULL) {
2671 return (NULL);
2672 }
William M. Bracke7091952004-05-11 15:09:58 +00002673 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002674 ret->id = xmlSchemaGetProp(ctxt, node, "id");
2675 processContents = xmlSchemaGetProp(ctxt, node, "processContents");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002676 if ((processContents == NULL)
2677 || (xmlStrEqual(processContents, (const xmlChar *) "strict"))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002678 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002679 } else if (xmlStrEqual(processContents, (const xmlChar *) "skip")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002680 ret->processContents = XML_SCHEMAS_ANY_SKIP;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 } else if (xmlStrEqual(processContents, (const xmlChar *) "lax")) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00002682 ret->processContents = XML_SCHEMAS_ANY_LAX;
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00002684 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002685 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
William M. Bracke7091952004-05-11 15:09:58 +00002686 "anyAttribute has unexpected content "
2687 "for processContents: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002688 processContents, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002689 ret->processContents = XML_SCHEMAS_ANY_STRICT;
Daniel Veillard3646d642004-06-02 19:19:14 +00002690 }
2691 /*
2692 * Build the namespace constraints.
2693 */
2694 nsConstraint = xmlSchemaGetProp(ctxt, node, "namespace");
William M. Brack803812b2004-06-03 02:11:24 +00002695 if ((nsConstraint == NULL) || (xmlStrEqual(nsConstraint, BAD_CAST "##any")))
Daniel Veillard3646d642004-06-02 19:19:14 +00002696 ret->any = 1;
William M. Brack803812b2004-06-03 02:11:24 +00002697 else if (xmlStrEqual(nsConstraint, BAD_CAST "##other")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002698 ret->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
2699 if (ret->negNsSet == NULL) {
2700 xmlSchemaFreeWildcard(ret);
2701 return (NULL);
2702 }
2703 ret->negNsSet->value = schema->targetNamespace;
2704 } else {
2705 cur = nsConstraint;
2706 do {
2707 while (IS_BLANK_CH(*cur))
2708 cur++;
2709 end = cur;
2710 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
2711 end++;
2712 if (end == cur)
2713 break;
2714 member = xmlStrndup(cur, end - cur);
William M. Brack803812b2004-06-03 02:11:24 +00002715 if ((xmlStrEqual(member, BAD_CAST "##other")) ||
2716 (xmlStrEqual(member, BAD_CAST "##any"))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002717 xmlSchemaPErr(ctxt, ret->node, XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
2718 "The namespace constraint of an anyAttribute "
2719 "is a set and must not contain \"%s\"\n",
2720 member, NULL);
2721 } else {
2722 /*
2723 * TODO: Validate the value (anyURI).
2724 */
William M. Brack803812b2004-06-03 02:11:24 +00002725 if (xmlStrEqual(member, BAD_CAST "##targetNamespace")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002726 dictMember = schema->targetNamespace;
William M. Brack803812b2004-06-03 02:11:24 +00002727 } else if (xmlStrEqual(member, BAD_CAST "##local")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00002728 dictMember = NULL;
2729 } else
2730 dictMember = xmlDictLookup(ctxt->dict, member, -1);
2731 /*
2732 * Avoid dublicate namespaces.
2733 */
2734 tmp = ret->nsSet;
2735 while (tmp != NULL) {
2736 if (dictMember == tmp->value)
2737 break;
2738 tmp = tmp->next;
2739 }
2740 if (tmp == NULL) {
2741 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
2742 if (tmp == NULL) {
2743 xmlFree(member);
2744 xmlSchemaFreeWildcard(ret);
2745 return (NULL);
2746 }
2747 tmp->value = dictMember;
2748 tmp->next = NULL;
2749 if (ret->nsSet == NULL)
2750 ret->nsSet = tmp;
2751 else
2752 lastNs->next = tmp;
2753 lastNs = tmp;
2754 }
2755
2756 }
2757 xmlFree(member);
2758 cur = end;
2759 } while (*cur != 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00002760 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002761
2762 child = node->children;
2763 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2765 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 }
2767 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002768 xmlSchemaPErr2(ctxt, node, child,
2769 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
Daniel Veillard3646d642004-06-02 19:19:14 +00002770 "anyAttribute has unexpected content\n",
2771 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002772 }
2773
2774 return (ret);
2775}
2776
2777
2778/**
2779 * xmlSchemaParseAttribute:
2780 * @ctxt: a schema validation context
2781 * @schema: the schema being built
2782 * @node: a subtree containing XML Schema informations
2783 *
2784 * parse a XML schema Attrribute declaration
2785 * *WARNING* this interface is highly subject to change
2786 *
William M. Bracke7091952004-05-11 15:09:58 +00002787 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00002788 */
2789static xmlSchemaAttributePtr
2790xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00002791 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002792{
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002793 const xmlChar *name, *refNs = NULL, *ref = NULL, *attrVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00002794 xmlSchemaAttributePtr ret;
2795 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002796 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00002797 int hasRefType = 0;
William M. Bracke7091952004-05-11 15:09:58 +00002798
2799 /*
2800 * Note that the w3c spec assumes the schema to be validated with schema
2801 * for schemas beforehand.
2802 *
2803 * 3.2.3 Constraints on XML Representations of Attribute Declarations
2804 *
2805 * TODO: Complete implementation of:
2806 * 3.2.6 Schema Component Constraint: Attribute Declaration Properties
2807 * Correct
2808 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002809
2810 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
2811 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002812
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002813 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00002814 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002815 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00002816 /* 3.2.3 : 3.1
2817 * One of ref or name must be present, but not both
2818 */
2819 if (ref == NULL) {
2820 xmlSchemaPErr(ctxt, node,
2821 XML_SCHEMAP_ATTR_NONAME_NOREF,
2822 "Attribute declaration has no \"name\" or \"ref\"\n",
2823 NULL, NULL);
2824 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002825 }
William M. Bracke7091952004-05-11 15:09:58 +00002826 hasRefType = 1;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002827 snprintf(buf, 99, "anonattr %d", ctxt->counter++ + 1);
2828 name = (const xmlChar *) buf;
2829 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002830 if (!topLevel) {
2831 /* 3.2.3 : 3.2
2832 * If ref is present, then all of <simpleType>,
2833 * form and type must be absent.
2834 */
2835 if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2836 xmlSchemaPErr(ctxt, node,
2837 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2838 "Attribute declaration %s has \"ref\", thus "
2839 "\"form\" must be absent\n", name, NULL);
2840 }
2841 if (xmlSchemaGetProp(ctxt, node, "type") != NULL) {
2842 xmlSchemaPErr(ctxt, node,
2843 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2844 "Attribute declaration %s has \"ref\", thus "
2845 "\"type\" must be absent\n", name, NULL);
2846 }
2847 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002848 } else {
William M. Bracke7091952004-05-11 15:09:58 +00002849 const xmlChar *ns = NULL;
2850 /* 3.2.3 : 3.1
2851 * One of ref or name must be present, but not both
2852 */
2853 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
2854 xmlSchemaPErr(ctxt, node,
2855 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
Daniel Veillard3646d642004-06-02 19:19:14 +00002856 "Attribute declaration \"%s\" has both, \"name\" and "
2857 "\"ref\"\n", name, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002858 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002859
William M. Bracke7091952004-05-11 15:09:58 +00002860 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
2861 /* Evaluate the target namespace */
2862 if (schema->targetNamespace != NULL) {
2863 if (topLevel) {
2864 ns = schema->targetNamespace;
2865 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
2866 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
2867 BAD_CAST "qualified")) {
2868 ns = schema->targetNamespace;
2869 }
2870 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
2871 ns = schema->targetNamespace;
2872 }
2873 }
2874 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillard3646d642004-06-02 19:19:14 +00002875 if (ret == NULL)
2876 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00002877 /* 3.2.6 Schema Component Constraint: xmlns Not Allowed */
2878 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
2879 xmlSchemaPErr(ctxt, node,
2880 XML_SCHEMAP_INVALID_ATTR_NAME,
2881 "The name of an attribute declaration must not match "
2882 "\"xmlns\".\n", NULL, NULL);
2883 }
2884
2885 /* 3.2.6 Schema Component Constraint: xsi: Not Allowed */
2886 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
2887 xmlSchemaPErr(ctxt, node,
2888 XML_SCHEMAP_INVALID_ATTR_NAME,
2889 "The target namespace of an attribute declaration, "
2890 "must not match \"http://www.w3.org/2001/"
2891 "XMLSchema-instance\"", NULL, NULL);
2892 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002893 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002894 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002895 return (NULL);
2896 }
William M. Bracke7091952004-05-11 15:09:58 +00002897 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Daniel Veillard3646d642004-06-02 19:19:14 +00002898 if (topLevel)
2899 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
William M. Bracke7091952004-05-11 15:09:58 +00002900
2901 /* Handle the "use" attribute. */
2902 attrVal = xmlSchemaGetProp(ctxt, node, "use");
2903 if (attrVal != NULL) {
2904 if (xmlStrEqual(attrVal, BAD_CAST "optional"))
2905 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
2906 else if (xmlStrEqual(attrVal, BAD_CAST "prohibited"))
2907 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
2908 else if (xmlStrEqual(attrVal, BAD_CAST "required"))
2909 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
2910 else
2911 xmlSchemaPErr(ctxt, node,
2912 XML_SCHEMAP_INVALID_ATTR_USE,
2913 "Attribute declaration %s has an invalid "
2914 "value for \"use\"\n", name, NULL);
2915 } else
2916 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002917
William M. Bracke7091952004-05-11 15:09:58 +00002918
2919 if (xmlSchemaGetProp(ctxt, node, "default") != NULL) {
2920 /* 3.2.3 : 1
2921 * default and fixed must not both be present.
2922 */
2923 if (xmlSchemaGetProp(ctxt, node, "fixed") != NULL) {
2924 xmlSchemaPErr(ctxt, node,
2925 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2926 "Attribute declaration has both, \"default\" "
2927 "and \"fixed\"\n", NULL, NULL);
2928 }
2929 /* 3.2.3 : 2
2930 * If default and use are both present, use must have
2931 * the actual value optional.
2932 */
2933 if (ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) {
2934 xmlSchemaPErr(ctxt, node,
2935 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2936 "Attribute declaration has \"default\" but "
2937 "\"use\" is not \"optional\"\n", NULL, NULL);
2938 }
2939 }
Daniel Veillardc85d0fe2004-04-16 16:46:51 +00002940
Daniel Veillard4255d502002-04-16 15:50:10 +00002941 ret->ref = ref;
2942 ret->refNs = refNs;
William M. Bracke7091952004-05-11 15:09:58 +00002943 /*
2944 * The setting of XML_SCHEMAS_ATTR_NSDEFAULT is not needed anymore,
2945 * since the target namespace was already evaluated and took
2946 * attributeFormDefault into account.
2947 */
2948 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002949 if ((ret->targetNamespace != NULL) &&
2950 ((schema->flags & XML_SCHEMAS_QUALIF_ATTR) == 0) &&
2951 (xmlStrEqual(ret->targetNamespace, schema->targetNamespace)))
2952 ret->flags |= XML_SCHEMAS_ATTR_NSDEFAULT;
William M. Bracke7091952004-05-11 15:09:58 +00002953 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002954 ret->typeName = xmlGetQNameProp(ctxt, node, "type", &(ret->typeNs));
William M. Bracke7091952004-05-11 15:09:58 +00002955 if (ret->typeName != NULL)
2956 hasRefType = 1;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00002957 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00002958 child = node->children;
2959 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002960 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
2961 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002962 }
2963 if (IS_SCHEMA(child, "simpleType")) {
William M. Bracke7091952004-05-11 15:09:58 +00002964 if (hasRefType) {
2965 /* 3.2.3 : 4
2966 * type and <simpleType> must not both be present.
2967 *
2968 * TODO: XML_SCHEMAP_INVALID_ATTR_COMBINATION seems not to be
2969 * a proper error type here.
2970 */
2971 xmlSchemaPErr2(ctxt, node, child,
2972 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
2973 "Attribute declaration %s has both (\"ref\" or "
2974 "\"type\") and <simpleType>\n", name, NULL);
2975 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00002976 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002977 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 }
2979 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002980 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ATTR_CHILD,
2981 "attribute %s has unexpected content\n", name,
2982 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002983 }
2984
2985 return (ret);
2986}
2987
2988/**
2989 * xmlSchemaParseAttributeGroup:
2990 * @ctxt: a schema validation context
2991 * @schema: the schema being built
2992 * @node: a subtree containing XML Schema informations
2993 *
2994 * parse a XML schema Attribute Group declaration
2995 * *WARNING* this interface is highly subject to change
2996 *
2997 * Returns the attribute group or NULL in case of error.
2998 */
2999static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003000xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003001 xmlSchemaPtr schema, xmlNodePtr node,
3002 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003003{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003004 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003005 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003007 const xmlChar *oldcontainer;
3008 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003009
3010 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3011 return (NULL);
3012 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003013 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003015 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3016 if (ref == NULL) {
3017 xmlSchemaPErr2(ctxt, node, child,
3018 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
3019 "AttributeGroup has no name nor ref\n", NULL,
3020 NULL);
3021 return (NULL);
3022 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003023 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
3024 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003025 if (name == NULL) {
3026 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
3027 return (NULL);
3028 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003029 }
3030 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
3031 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003032 return (NULL);
3033 }
3034 ret->ref = ref;
3035 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00003036 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003037 if (topLevel)
3038 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00003039 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 child = node->children;
3041 ctxt->container = name;
3042 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003043 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3044 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003045 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003046 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
3047 /* Seems that this can be removed. */
3048 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00003049 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003050 (IS_SCHEMA(child, "attributeGroup"))) {
3051 attr = NULL;
3052 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003053 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003054 } else if (IS_SCHEMA(child, "attributeGroup")) {
3055 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003056 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003057 }
3058 if (attr != NULL) {
3059 if (last == NULL) {
3060 ret->attributes = attr;
3061 last = attr;
3062 } else {
3063 last->next = attr;
3064 last = attr;
3065 }
3066 }
3067 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003068 }
3069 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003070 TODO
3071 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003073 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003075 xmlSchemaPErr2(ctxt, node, child,
3076 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
3077 "attribute group %s has unexpected content\n", name,
3078 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003080 ctxt->container = oldcontainer;
3081 return (ret);
3082}
3083
3084/**
3085 * xmlSchemaParseElement:
3086 * @ctxt: a schema validation context
3087 * @schema: the schema being built
3088 * @node: a subtree containing XML Schema informations
3089 *
3090 * parse a XML schema Element declaration
3091 * *WARNING* this interface is highly subject to change
3092 *
William M. Bracke7091952004-05-11 15:09:58 +00003093 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00003094 */
3095static xmlSchemaElementPtr
3096xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003097 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003098{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003099 const xmlChar *name, *fixed;
3100 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003101 xmlSchemaElementPtr ret;
3102 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103 const xmlChar *oldcontainer;
3104 char buf[100];
William M. Bracke7091952004-05-11 15:09:58 +00003105 xmlAttrPtr attr;
3106
3107 /* 3.3.3 Constraints on XML Representations of Element Declarations */
3108 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003109
3110 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3111 return (NULL);
3112 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003113 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003114 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003115 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
William M. Bracke7091952004-05-11 15:09:58 +00003116 /* 3.3.3 : 2.1
3117 * One of ref or name must be present, but not both
3118 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003119 if (ref == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00003120 xmlSchemaPErr(ctxt, node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003121 XML_SCHEMAP_ELEM_NONAME_NOREF,
Daniel Veillard3646d642004-06-02 19:19:14 +00003122 "Element declaration has no name nor ref\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003123 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003124 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003125
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003126 snprintf(buf, 99, "anonelem %d", ctxt->counter++ + 1);
3127 name = (const xmlChar *) buf;
3128 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
3129 } else {
William M. Bracke7091952004-05-11 15:09:58 +00003130 const xmlChar *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003131
William M. Bracke7091952004-05-11 15:09:58 +00003132 /* Evaluate the target namespace */
3133 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003134 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00003135 ns = schema->targetNamespace;
3136 } else if (xmlSchemaGetProp(ctxt, node, "form") != NULL) {
3137 if (xmlStrEqual( xmlSchemaGetProp(ctxt, node, "form"),
3138 BAD_CAST "qualified")) {
3139 ns = schema->targetNamespace;
3140 }
3141 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) {
3142 ns = schema->targetNamespace;
3143 }
3144 }
3145 /*local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
3146 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
3147 /* 3.3.3 : 2.1
3148 * One of ref or name must be present, but not both
3149 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003150 if ((!topLevel) && (xmlSchemaGetProp(ctxt, node, "ref") != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003151 xmlSchemaPErr(ctxt, node,
3152 XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3153 "Element declaration has both, \"name\" and "
3154 "\"ref\"\n", NULL, NULL);
3155 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003156 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003157 if (ret != NULL)
3158 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00003159 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003160 return (NULL);
3161 }
3162 ret->type = XML_SCHEMA_TYPE_ELEMENT;
3163 ret->ref = ref;
3164 ret->refNs = refNs;
3165 if (ref != NULL)
3166 ret->flags |= XML_SCHEMAS_ELEM_REF;
William M. Bracke7091952004-05-11 15:09:58 +00003167
3168 /* 3.3.3 : 2.2 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003169 if ((!topLevel) && (ref != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003170 attr = node->properties;
3171 while (attr != NULL) {
3172 if ((attr->ns == NULL) &&
3173 (!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
3174 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
3175 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
3176 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
3177
3178 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3179 "Element declaration %s: only minOccurs, maxOccurs "
3180 "and id are allowed in addition to ref\n",
3181 ret->name, NULL);
3182 }
3183 attr = attr->next;
3184 }
3185 }
3186
Daniel Veillard3646d642004-06-02 19:19:14 +00003187 if (topLevel) {
3188 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
Daniel Veillard4255d502002-04-16 15:50:10 +00003189 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Daniel Veillard3646d642004-06-02 19:19:14 +00003190 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
3192 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
3193 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
Daniel Veillard3646d642004-06-02 19:19:14 +00003194 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 ctxt->container = name;
3196
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003197 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003198 ret->namedType =
William M. Bracke7091952004-05-11 15:09:58 +00003199 xmlGetQNameProp(ctxt, node, "type", &(ret->namedTypeNs));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 ret->substGroup =
3201 xmlGetQNameProp(ctxt, node, "substitutionGroup",
3202 &(ret->substGroupNs));
Daniel Veillard3646d642004-06-02 19:19:14 +00003203 if ((ret->substGroup != NULL) && (!topLevel)) {
William M. Bracke7091952004-05-11 15:09:58 +00003204 /* 3.3.6 : 3 */
3205 /*
3206 * TODO: This seems to be redundant, since the schema for schemas
3207 * already prohibits the use of the "substitutionGroup" attribute
3208 * in local element declarations.
3209 */
3210 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_ATTR_COMBINATION,
3211 "Element declaration %s: substitutionGroup is allowed "
3212 "on top-level declarations only\n", ret->name, NULL);
3213
3214 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003215 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
Daniel Veillard4255d502002-04-16 15:50:10 +00003216 ret->minOccurs = xmlGetMinOccurs(ctxt, node);
3217 ret->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003218
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003219 ret->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 if ((ret->value != NULL) && (fixed != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00003221 /* 3.3.3 : 1
3222 * default and fixed must not both be present.
3223 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003224 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_ELEM_DEFAULT_FIXED,
3225 "Element %s has both default and fixed\n",
3226 ret->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 } else if (fixed != NULL) {
3228 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003229 ret->value = fixed;
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 }
3231
3232 child = node->children;
3233 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003234 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3235 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003236 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003237
William M. Bracke7091952004-05-11 15:09:58 +00003238 if (ref != NULL) {
3239 /* 3.3.3 (2.2) */
3240 while (child != NULL) {
3241 if ((IS_SCHEMA(child, "complexType")) ||
3242 (IS_SCHEMA(child, "simpleType")) ||
3243 (IS_SCHEMA(child, "unique")) ||
3244 (IS_SCHEMA(child, "key")) ||
3245 (IS_SCHEMA(child, "keyref"))) {
3246
3247 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_REF_AND_CONTENT,
3248 "Element declaration %s: only annotation is "
3249 "allowed as content in addition to ref\n",
3250 ret->name, NULL);
3251 } else {
3252 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3253 "element %s has unexpected content\n", name, NULL);
3254 }
3255 child = child->next;
3256 }
3257 } else {
3258 if (IS_SCHEMA(child, "complexType")) {
3259 /* 3.3.3 : 3
3260 * type and either <simpleType> or <complexType> are mutually
3261 * exclusive
3262 */
3263 if (ret->namedType != NULL) {
3264 xmlSchemaPErr2(ctxt, node, child,
3265 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3266 "Element declaration %s has both \"type\" "
3267 "and a local complex type\n",
3268 ret->name, NULL);
3269 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003270 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003271 child = child->next;
3272 } else if (IS_SCHEMA(child, "simpleType")) {
3273 /* 3.3.3 : 3
3274 * type and either <simpleType> or <complexType> are
3275 * mutually exclusive
3276 */
3277 if (ret->namedType != NULL) {
3278 xmlSchemaPErr2(ctxt, node, child,
3279 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION,
3280 "Element declaration %s has both \"type\" "
3281 "and a local simple type\n",
3282 ret->name, NULL);
3283 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00003284 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00003285 child = child->next;
3286 }
3287
3288 while ((IS_SCHEMA(child, "unique")) ||
3289 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
3290 TODO child = child->next;
3291 }
3292 if (child != NULL) {
3293 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ELEM_CHILD,
3294 "element %s has unexpected content\n", name, NULL);
3295 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003296 }
3297
3298 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00003299 return (ret);
3300}
3301
3302/**
3303 * xmlSchemaParseUnion:
3304 * @ctxt: a schema validation context
3305 * @schema: the schema being built
3306 * @node: a subtree containing XML Schema informations
3307 *
3308 * parse a XML schema Union definition
3309 * *WARNING* this interface is highly subject to change
3310 *
William M. Bracke7091952004-05-11 15:09:58 +00003311 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003312 * 1 in case of success.
3313 */
3314static xmlSchemaTypePtr
3315xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003317{
3318 xmlSchemaTypePtr type, subtype, last = NULL;
3319 xmlNodePtr child = NULL;
3320 xmlChar name[30];
3321
3322 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3323 return (NULL);
3324
3325
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003326 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003327 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003328 if (type == NULL)
3329 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003330 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00003331 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003332 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003333 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00003334
3335 child = node->children;
3336 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003337 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3338 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003339 }
3340 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003341 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003342 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003343 if (subtype != NULL) {
3344 if (last == NULL) {
3345 type->subtypes = subtype;
3346 last = subtype;
3347 } else {
3348 last->next = subtype;
3349 last = subtype;
3350 }
3351 last->next = NULL;
3352 }
3353 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003354 }
3355 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003356 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
3357 "Union %s has unexpected content\n", type->name,
3358 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003359 }
3360 return (type);
3361}
3362
3363/**
3364 * xmlSchemaParseList:
3365 * @ctxt: a schema validation context
3366 * @schema: the schema being built
3367 * @node: a subtree containing XML Schema informations
3368 *
3369 * parse a XML schema List definition
3370 * *WARNING* this interface is highly subject to change
3371 *
William M. Bracke7091952004-05-11 15:09:58 +00003372 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003373 * 1 in case of success.
3374 */
3375static xmlSchemaTypePtr
3376xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003377 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003378{
3379 xmlSchemaTypePtr type, subtype;
3380 xmlNodePtr child = NULL;
3381 xmlChar name[30];
Daniel Veillard01fa6152004-06-29 17:04:39 +00003382 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003383
3384 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3385 return (NULL);
3386
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003387 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003388 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003389 if (type == NULL)
3390 return (NULL);
3391 type->node = node;
3392 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003393 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003394
3395 child = node->children;
3396 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3398 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003400 /*
3401 * Check type of "itemType".
3402 */
3403 attr = xmlSchemaGetPropNode(node, "itemType");
3404 if (attr != NULL) {
3405 type->base = xmlGetQNameProp(ctxt, node, "itemType", &(type->baseNs));
3406 xmlSchemaParseSchemaAttrValue(ctxt, attr,
3407 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
3408
3409 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003410 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003411 if (IS_SCHEMA(child, "simpleType")) {
3412 subtype = (xmlSchemaTypePtr)
3413 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
3414 type->subtypes = subtype;
3415 /*
3416 * This is a hack to save the information that a local
3417 * simple type was defined.
3418 */
3419 type->baseType = subtype;
3420 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003421 }
3422 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
3424 "List %s has unexpected content\n", type->name,
3425 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003426 }
3427 return (type);
3428}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003429
Daniel Veillard4255d502002-04-16 15:50:10 +00003430/**
3431 * xmlSchemaParseSimpleType:
3432 * @ctxt: a schema validation context
3433 * @schema: the schema being built
3434 * @node: a subtree containing XML Schema informations
3435 *
3436 * parse a XML schema Simple Type definition
3437 * *WARNING* this interface is highly subject to change
3438 *
William M. Bracke7091952004-05-11 15:09:58 +00003439 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003440 * 1 in case of success.
3441 */
3442static xmlSchemaTypePtr
3443xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003444 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003445{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003446 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00003447 xmlNodePtr child = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003448 const xmlChar *propVal;
Daniel Veillard4255d502002-04-16 15:50:10 +00003449
3450 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3451 return (NULL);
3452
Daniel Veillard01fa6152004-06-29 17:04:39 +00003453 ctxtType = ctxt->ctxtType;
3454 propVal = xmlSchemaGetProp(ctxt, node, "name");
3455 if (propVal == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003456 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003457
William M. Bracke7091952004-05-11 15:09:58 +00003458 snprintf(buf, 99, "simpleType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003459 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00003460 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00003461 if (!topLevel) {
3462 xmlSchemaPErr(ctxt, node,
3463 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3464 "The attribute \"name\" is not allowed on a local "
3465 "simpleType definition\n",
3466 propVal, NULL);
3467 return (NULL);
3468 }
3469 /*
3470 * "name" has to be of type NCName.
3471 * TODO: Actually this should be validated by the schema for schemas.
3472 */
3473 if (xmlSchemaParseSchemaAttrValue(ctxt,
3474 xmlSchemaGetPropNode(node, BAD_CAST "name"),
3475 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME)) != 0)
3476 return (NULL);
3477 type = xmlSchemaAddType(ctxt, schema, propVal, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003478 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003479 if (type == NULL)
3480 return (NULL);
3481 type->node = node;
3482 type->type = XML_SCHEMA_TYPE_SIMPLE;
Daniel Veillard3646d642004-06-02 19:19:14 +00003483 if (topLevel)
3484 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003485 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003486 propVal = xmlSchemaGetProp(ctxt, node, "final");
3487 if (propVal == NULL) {
3488 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
3489 } else {
3490 if (xmlStrEqual(propVal, BAD_CAST "#all")) {
3491 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3492 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3493 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3494 } else {
3495 const xmlChar *end, *cur = propVal;
3496 xmlChar *item;
3497
3498 do {
3499 while (IS_BLANK_CH(*cur))
3500 cur++;
3501 end = cur;
3502 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
3503 end++;
3504 if (end == cur)
3505 break;
3506 item = xmlStrndup(cur, end - cur);
3507 if (xmlStrEqual(item, BAD_CAST "restriction")) {
3508 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) == 0)
3509 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
3510 } else if (xmlStrEqual(item, BAD_CAST "list")) {
3511 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_LIST) == 0)
3512 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
3513 } else if (xmlStrEqual(item, BAD_CAST "union")) {
3514 if ((type->flags & XML_SCHEMAS_TYPE_FINAL_UNION) == 0)
3515 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
3516 } else {
3517 xmlSchemaPErr(ctxt, node,
3518 XML_SCHEMAS_ERR_INTERNAL,
3519 "The attribute \"final\" of type \"%s\" "
3520 "has an invalid value\n",
3521 type->name, NULL);
3522 }
3523 if (item != NULL)
3524 xmlFree(item);
3525 cur = end;
3526 } while (*cur != 0);
3527 }
3528 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003529 child = node->children;
3530 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003531 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3532 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 }
3534 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003535 ctxt->ctxtType = type;
3536 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00003537 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003538 subtype = (xmlSchemaTypePtr)
3539 xmlSchemaParseRestriction(ctxt, schema, child, 1);
3540 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 subtype = (xmlSchemaTypePtr)
3543 xmlSchemaParseList(ctxt, schema, child);
3544 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003545 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003546 subtype = (xmlSchemaTypePtr)
3547 xmlSchemaParseUnion(ctxt, schema, child);
3548 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003549 }
3550 type->subtypes = subtype;
3551 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003552 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00003553 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3554 "SimpleType \"%s\" has unexpected content\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003555 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003556 } else {
3557 if (subtype == NULL) {
3558 xmlSchemaPErr2(ctxt, node, child,
3559 XML_SCHEMAP_S4S_ELEM_MISSING,
3560 "SimpleType \"%s\" must have one of <restriction> or "
3561 "<list> or <union> as a child\n",
3562 type->name, NULL);
3563 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003564 }
3565
Daniel Veillard01fa6152004-06-29 17:04:39 +00003566 ctxt->ctxtType = ctxtType;
3567
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 return (type);
3569}
3570
3571
3572/**
3573 * xmlSchemaParseGroup:
3574 * @ctxt: a schema validation context
3575 * @schema: the schema being built
3576 * @node: a subtree containing XML Schema informations
3577 *
3578 * parse a XML schema Group definition
3579 * *WARNING* this interface is highly subject to change
3580 *
William M. Bracke7091952004-05-11 15:09:58 +00003581 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003582 * 1 in case of success.
3583 */
3584static xmlSchemaTypePtr
3585xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003586 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003587{
3588 xmlSchemaTypePtr type, subtype;
3589 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003590 const xmlChar *name;
3591 const xmlChar *ref = NULL, *refNs = NULL;
3592 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00003593
3594 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3595 return (NULL);
3596
3597
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003598 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003600 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
3601 if (ref == NULL) {
3602 xmlSchemaPErr2(ctxt, node, child,
3603 XML_SCHEMAP_GROUP_NONAME_NOREF,
3604 "Group has no name nor ref\n", NULL, NULL);
3605 return (NULL);
3606 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003607 if (refNs == NULL)
3608 refNs = schema->targetNamespace;
3609 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
3610 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003612 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003613 if (type == NULL)
3614 return (NULL);
3615 type->node = node;
3616 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00003617 if (topLevel)
3618 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003619 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 type->ref = ref;
3621 type->refNs = refNs;
3622 type->minOccurs = xmlGetMinOccurs(ctxt, node);
3623 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
3624
3625 child = node->children;
3626 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003627 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3628 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 }
3630 subtype = NULL;
3631 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003632 subtype = (xmlSchemaTypePtr)
3633 xmlSchemaParseAll(ctxt, schema, child);
3634 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 subtype = xmlSchemaParseChoice(ctxt, schema, child);
3637 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639 subtype = (xmlSchemaTypePtr)
3640 xmlSchemaParseSequence(ctxt, schema, child);
3641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 }
3643 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003644 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
3647 "Group %s has unexpected content\n", type->name,
3648 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 }
3650
3651 return (type);
3652}
3653
3654/**
3655 * xmlSchemaParseAll:
3656 * @ctxt: a schema validation context
3657 * @schema: the schema being built
3658 * @node: a subtree containing XML Schema informations
3659 *
3660 * parse a XML schema All definition
3661 * *WARNING* this interface is highly subject to change
3662 *
William M. Bracke7091952004-05-11 15:09:58 +00003663 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 * 1 in case of success.
3665 */
3666static xmlSchemaTypePtr
3667xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003669{
3670 xmlSchemaTypePtr type, subtype, last = NULL;
3671 xmlNodePtr child = NULL;
3672 xmlChar name[30];
3673
3674 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3675 return (NULL);
3676
3677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003679 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003680 if (type == NULL)
3681 return (NULL);
3682 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00003683 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003684 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003686 if (type->minOccurs > 1)
3687 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3688 "invalid value for minOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003689 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00003690 if (type->maxOccurs > 1)
3691 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
3692 "invalid value for maxOccurs (must be 0 or 1)\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003693
3694 child = node->children;
3695 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003696 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3697 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003698 }
3699 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003700 subtype = (xmlSchemaTypePtr)
3701 xmlSchemaParseElement(ctxt, schema, child, 0);
3702 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00003703 if (subtype->minOccurs > 1)
3704 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
3705 "invalid value for minOccurs (must be 0 or 1)\n",
3706 NULL, NULL);
3707 if (subtype->maxOccurs > 1)
3708 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
3709 "invalid value for maxOccurs (must be 0 or 1)\n",
3710 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003711 if (last == NULL) {
3712 type->subtypes = subtype;
3713 last = subtype;
3714 } else {
3715 last->next = subtype;
3716 last = subtype;
3717 }
3718 last->next = NULL;
3719 }
3720 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 }
3722 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
3724 "All %s has unexpected content\n", type->name,
3725 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 }
3727
3728 return (type);
3729}
3730
3731/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003732 * xmlSchemaImportSchema
3733 *
3734 * @ctxt: a schema validation context
3735 * @schemaLocation: an URI defining where to find the imported schema
3736 *
3737 * import a XML schema
3738 * *WARNING* this interface is highly subject to change
3739 *
3740 * Returns -1 in case of error and 1 in case of success.
3741 */
3742static xmlSchemaImportPtr
3743xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
3744 const xmlChar *schemaLocation)
3745{
3746 xmlSchemaImportPtr import;
3747 xmlSchemaParserCtxtPtr newctxt;
3748
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003749 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00003750 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003751 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00003752 NULL);
3753 return (NULL);
3754 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003755 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
3756 /* Keep the same dictionnary for parsing, really */
3757 xmlDictReference(ctxt->dict);
3758 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003759 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003760 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
3761
Daniel Veillard1d913862003-11-21 00:28:39 +00003762 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
3763 ctxt->userData);
3764
3765 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
3766 if (import == NULL) {
3767 xmlSchemaPErrMemory(NULL, "allocating imported schema",
3768 NULL);
3769 xmlSchemaFreeParserCtxt(newctxt);
3770 return (NULL);
3771 }
3772
3773 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003774 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00003775 import->schema = xmlSchemaParse(newctxt);
3776
3777 if (import->schema == NULL) {
3778 /* FIXME use another error enum here ? */
3779 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
3780 "failed to import schema at location %s\n",
3781 schemaLocation, NULL);
3782
3783 xmlSchemaFreeParserCtxt(newctxt);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00003784 if (import->schemaLocation != NULL)
3785 xmlFree((xmlChar *)import->schemaLocation);
Daniel Veillard1d913862003-11-21 00:28:39 +00003786 xmlFree(import);
3787 return NULL;
3788 }
3789
3790 xmlSchemaFreeParserCtxt(newctxt);
3791 return import;
3792}
3793
3794
3795/**
Daniel Veillard5a872412002-05-22 06:40:27 +00003796 * xmlSchemaParseImport:
3797 * @ctxt: a schema validation context
3798 * @schema: the schema being built
3799 * @node: a subtree containing XML Schema informations
3800 *
3801 * parse a XML schema Import definition
3802 * *WARNING* this interface is highly subject to change
3803 *
William M. Bracke7091952004-05-11 15:09:58 +00003804 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00003805 * 1 in case of success.
3806 */
3807static int
3808xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003809 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00003810{
3811 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00003812 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003813 const xmlChar *namespace;
3814 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00003815 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00003816 xmlURIPtr check;
3817
Daniel Veillard1d913862003-11-21 00:28:39 +00003818
Daniel Veillard5a872412002-05-22 06:40:27 +00003819 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3820 return (-1);
3821
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003822 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00003823 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003824 check = xmlParseURI((const char *) namespace);
3825 if (check == NULL) {
3826 xmlSchemaPErr2(ctxt, node, child,
3827 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
3828 "Import namespace attribute is not an URI: %s\n",
3829 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003830 return (-1);
3831 } else {
3832 xmlFreeURI(check);
3833 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003834 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003835 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00003836 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003837 xmlChar *base = NULL;
3838 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003839 check = xmlParseURI((const char *) schemaLocation);
3840 if (check == NULL) {
3841 xmlSchemaPErr2(ctxt, node, child,
3842 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
3843 "Import schemaLocation attribute is not an URI: %s\n",
3844 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003845 return (-1);
3846 } else {
3847 xmlFreeURI(check);
3848 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003849 base = xmlNodeGetBase(node->doc, node);
3850 if (base == NULL) {
3851 URI = xmlBuildURI(schemaLocation, node->doc->URL);
3852 } else {
3853 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003854 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00003855 }
Daniel Veillard1d913862003-11-21 00:28:39 +00003856 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003857 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
3858 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00003859 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003860 }
3861 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003862 schema->schemasImports = xmlHashCreate(10);
3863 if (schema->schemasImports == NULL) {
3864 xmlSchemaPErr2(ctxt, node, child,
3865 XML_SCHEMAP_FAILED_BUILD_IMPORT,
3866 "Internal: failed to build import table\n",
3867 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003868 return (-1);
3869 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003870 }
3871 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003872 import = xmlHashLookup(schema->schemasImports,
3873 XML_SCHEMAS_DEFAULT_NAMESPACE);
3874 if (import != NULL)
3875 previous = import->schemaLocation;
3876 else
3877 previous = NULL;
3878
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003879 if (schemaLocation != NULL) {
3880 if (previous != NULL) {
3881 if (!xmlStrEqual(schemaLocation, previous)) {
3882 xmlSchemaPErr2(ctxt, node, child,
3883 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003884 "Redefining import for default namespace "
3885 "with a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003886 schemaLocation, NULL);
3887 }
3888 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003889 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3890 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003891 return (-1);
3892 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 xmlHashAddEntry(schema->schemasImports,
3894 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00003895 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003896 }
3897 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003898 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003899 import = xmlHashLookup(schema->schemasImports, namespace);
3900 if (import != NULL)
3901 previous = import->schemaLocation;
3902 else
3903 previous = NULL;
3904
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003905 if (schemaLocation != NULL) {
3906 if (previous != NULL) {
3907 if (!xmlStrEqual(schemaLocation, previous)) {
3908 xmlSchemaPErr2(ctxt, node, child,
3909 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
William M. Bracke7091952004-05-11 15:09:58 +00003910 "Redefining import for namespace %s with "
3911 "a different URI: %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003912 namespace, schemaLocation);
3913 }
3914 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00003915 import = xmlSchemaImportSchema(ctxt, schemaLocation);
3916 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003917 return (-1);
3918 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003919 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
3920 if (namespace == NULL) {
3921 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003922 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_2,
Daniel Veillard3646d642004-06-02 19:19:14 +00003923 "There is no namespace attribute on the <import> "
3924 "element information item, so the imported document "
3925 "must have no targetNamespace attribute.\n",
3926 NULL, NULL);
3927 }
3928 } else {
3929 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00003930 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003931 "The namespace attribute \"%s\" of an <import> "
3932 "element information item must be identical to the "
3933 "targetNamespace attribute \"%s\" of the "
3934 "imported document.\n",
3935 namespace, import->schema->targetNamespace);
3936 } else {
William M. Brack767265d2004-06-03 10:50:29 +00003937 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillard3646d642004-06-02 19:19:14 +00003938 "The namespace attribute on the <import> "
3939 "element information item, requires the imported "
3940 "document to have a targetNamespace attribute "
3941 "with the value \"%s\".\n",
3942 namespace, NULL);
3943 }
3944 }
3945 xmlSchemaFreeImport(import);
3946 return (-1);
3947 }
3948
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003949 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00003950 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00003951
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003952 }
3953 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003954 }
Daniel Veillard5a872412002-05-22 06:40:27 +00003955
3956 child = node->children;
3957 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003958 /*
3959 * the annotations here are simply discarded ...
3960 */
3961 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00003962 }
3963 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
3965 "Import has unexpected content\n", NULL, NULL);
3966 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003967 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003968 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00003969}
3970
3971/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003972 * xmlSchemaCleanupDoc:
3973 * @ctxt: a schema validation context
3974 * @node: the root of the document.
3975 *
3976 * removes unwanted nodes in a schemas document tree
3977 */
3978static void
3979xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
3980{
3981 xmlNodePtr delete, cur;
3982
3983 if ((ctxt == NULL) || (root == NULL)) return;
3984
3985 /*
3986 * Remove all the blank text nodes
3987 */
3988 delete = NULL;
3989 cur = root;
3990 while (cur != NULL) {
3991 if (delete != NULL) {
3992 xmlUnlinkNode(delete);
3993 xmlFreeNode(delete);
3994 delete = NULL;
3995 }
3996 if (cur->type == XML_TEXT_NODE) {
3997 if (IS_BLANK_NODE(cur)) {
3998 if (xmlNodeGetSpacePreserve(cur) != 1) {
3999 delete = cur;
4000 }
4001 }
4002 } else if ((cur->type != XML_ELEMENT_NODE) &&
4003 (cur->type != XML_CDATA_SECTION_NODE)) {
4004 delete = cur;
4005 goto skip_children;
4006 }
4007
4008 /*
4009 * Skip to next node
4010 */
4011 if (cur->children != NULL) {
4012 if ((cur->children->type != XML_ENTITY_DECL) &&
4013 (cur->children->type != XML_ENTITY_REF_NODE) &&
4014 (cur->children->type != XML_ENTITY_NODE)) {
4015 cur = cur->children;
4016 continue;
4017 }
4018 }
4019 skip_children:
4020 if (cur->next != NULL) {
4021 cur = cur->next;
4022 continue;
4023 }
4024
4025 do {
4026 cur = cur->parent;
4027 if (cur == NULL)
4028 break;
4029 if (cur == root) {
4030 cur = NULL;
4031 break;
4032 }
4033 if (cur->next != NULL) {
4034 cur = cur->next;
4035 break;
4036 }
4037 } while (cur != NULL);
4038 }
4039 if (delete != NULL) {
4040 xmlUnlinkNode(delete);
4041 xmlFreeNode(delete);
4042 delete = NULL;
4043 }
4044}
4045
4046/**
4047 * xmlSchemaParseSchemaTopLevel:
4048 * @ctxt: a schema validation context
4049 * @schema: the schemas
4050 * @nodes: the list of top level nodes
4051 *
4052 * Returns the internal XML Schema structure built from the resource or
4053 * NULL in case of error
4054 */
4055static void
4056xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
4057 xmlSchemaPtr schema, xmlNodePtr nodes)
4058{
4059 xmlNodePtr child;
4060 xmlSchemaAnnotPtr annot;
4061
4062 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
4063 return;
4064
4065 child = nodes;
4066 while ((IS_SCHEMA(child, "include")) ||
4067 (IS_SCHEMA(child, "import")) ||
4068 (IS_SCHEMA(child, "redefine")) ||
4069 (IS_SCHEMA(child, "annotation"))) {
4070 if (IS_SCHEMA(child, "annotation")) {
4071 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4072 if (schema->annot == NULL)
4073 schema->annot = annot;
4074 else
4075 xmlSchemaFreeAnnot(annot);
4076 } else if (IS_SCHEMA(child, "import")) {
4077 xmlSchemaParseImport(ctxt, schema, child);
4078 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004079 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004080 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004081 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004082 } else if (IS_SCHEMA(child, "redefine")) {
4083 TODO
4084 }
4085 child = child->next;
4086 }
4087 while (child != NULL) {
4088 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004090 child = child->next;
4091 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004092 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004093 child = child->next;
4094 } else if (IS_SCHEMA(child, "element")) {
4095 xmlSchemaParseElement(ctxt, schema, child, 1);
4096 child = child->next;
4097 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004098 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004099 child = child->next;
4100 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004101 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004102 child = child->next;
4103 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004104 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004105 child = child->next;
4106 } else if (IS_SCHEMA(child, "notation")) {
4107 xmlSchemaParseNotation(ctxt, schema, child);
4108 child = child->next;
4109 } else {
4110 xmlSchemaPErr2(ctxt, NULL, child,
4111 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
4112 "Schemas: unexpected element %s here \n",
4113 child->name, NULL);
4114 child = child->next;
4115 }
4116 while (IS_SCHEMA(child, "annotation")) {
4117 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4118 if (schema->annot == NULL)
4119 schema->annot = annot;
4120 else
4121 xmlSchemaFreeAnnot(annot);
4122 child = child->next;
4123 }
4124 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004125 ctxt->parentItem = NULL;
4126 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004127}
4128
4129/**
4130 * xmlSchemaParseInclude:
4131 * @ctxt: a schema validation context
4132 * @schema: the schema being built
4133 * @node: a subtree containing XML Schema informations
4134 *
4135 * parse a XML schema Include definition
4136 *
William M. Bracke7091952004-05-11 15:09:58 +00004137 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004138 * 1 in case of success.
4139 */
4140static int
4141xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4142 xmlNodePtr node)
4143{
4144 xmlNodePtr child = NULL;
4145 const xmlChar *schemaLocation;
4146 xmlURIPtr check;
4147 xmlDocPtr doc;
4148 xmlNodePtr root;
4149 xmlSchemaIncludePtr include;
4150
4151
4152 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4153 return (-1);
4154
4155 /*
4156 * Preliminary step, extract the URI-Reference for the include and
4157 * make an URI from the base.
4158 */
4159 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
4160 if (schemaLocation != NULL) {
4161 xmlChar *base = NULL;
4162 xmlChar *URI = NULL;
4163 check = xmlParseURI((const char *) schemaLocation);
4164 if (check == NULL) {
4165 xmlSchemaPErr2(ctxt, node, child,
4166 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
4167 "Include schemaLocation attribute is not an URI: %s\n",
4168 schemaLocation, NULL);
4169 return (-1);
4170 } else {
4171 xmlFreeURI(check);
4172 }
4173 base = xmlNodeGetBase(node->doc, node);
4174 if (base == NULL) {
4175 URI = xmlBuildURI(schemaLocation, node->doc->URL);
4176 } else {
4177 URI = xmlBuildURI(schemaLocation, base);
4178 xmlFree(base);
4179 }
4180 if (URI != NULL) {
4181 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
4182 xmlFree(URI);
4183 }
4184 } else {
4185 xmlSchemaPErr2(ctxt, node, child,
4186 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
4187 "Include schemaLocation attribute missing\n",
4188 NULL, NULL);
4189 return (-1);
4190 }
4191
4192 child = node->children;
4193 while (IS_SCHEMA(child, "annotation")) {
4194 /*
4195 * the annotations here are simply discarded ...
4196 */
4197 child = child->next;
4198 }
4199 if (child != NULL) {
4200 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
4201 "Include has unexpected content\n", NULL, NULL);
4202 return (-1);
4203 }
4204
4205 /*
4206 * First step is to parse the input document into an DOM/Infoset
4207 */
4208 doc = xmlReadFile((const char *) schemaLocation, NULL,
4209 SCHEMAS_PARSE_OPTIONS);
4210 if (doc == NULL) {
4211 xmlSchemaPErr(ctxt, NULL,
4212 XML_SCHEMAP_FAILED_LOAD,
4213 "xmlSchemaParse: could not load %s\n",
4214 ctxt->URL, NULL);
4215 return(-1);
4216 }
4217
4218 /*
4219 * Then extract the root of the schema
4220 */
4221 root = xmlDocGetRootElement(doc);
4222 if (root == NULL) {
4223 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4224 XML_SCHEMAP_NOROOT,
4225 "schemas %s has no root", schemaLocation, NULL);
4226 xmlFreeDoc(doc);
4227 return (-1);
4228 }
4229
4230 /*
4231 * Remove all the blank text nodes
4232 */
4233 xmlSchemaCleanupDoc(ctxt, root);
4234
4235 /*
4236 * Check the schemas top level element
4237 */
4238 if (!IS_SCHEMA(root, "schema")) {
4239 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4240 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004241 "File %s is not a schema", schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004242 xmlFreeDoc(doc);
4243 return (-1);
4244 }
4245
4246 /*
4247 * register the include
4248 */
4249 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
4250 if (include == NULL) {
4251 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
4252 xmlFreeDoc(doc);
4253 return (-1);
4254 }
4255
4256 memset(include, 0, sizeof(xmlSchemaInclude));
4257 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
4258 include->doc = doc;
4259 include->next = schema->includes;
4260 schema->includes = include;
4261
4262
4263 /*
4264 * parse the declarations in the included file like if they
4265 * were in the original file.
4266 */
4267 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
4268
4269 return (1);
4270}
4271
4272/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 * xmlSchemaParseChoice:
4274 * @ctxt: a schema validation context
4275 * @schema: the schema being built
4276 * @node: a subtree containing XML Schema informations
4277 *
4278 * parse a XML schema Choice definition
4279 * *WARNING* this interface is highly subject to change
4280 *
William M. Bracke7091952004-05-11 15:09:58 +00004281 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 * 1 in case of success.
4283 */
4284static xmlSchemaTypePtr
4285xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004286 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004287{
4288 xmlSchemaTypePtr type, subtype, last = NULL;
4289 xmlNodePtr child = NULL;
4290 xmlChar name[30];
4291
4292 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4293 return (NULL);
4294
4295
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004296 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004297 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004298 if (type == NULL)
4299 return (NULL);
4300 type->node = node;
4301 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004302 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4304 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4305
4306 child = node->children;
4307 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004308 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4309 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004310 }
4311 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 (IS_SCHEMA(child, "group")) ||
4313 (IS_SCHEMA(child, "any")) ||
4314 (IS_SCHEMA(child, "choice")) ||
4315 (IS_SCHEMA(child, "sequence"))) {
4316 subtype = NULL;
4317 if (IS_SCHEMA(child, "element")) {
4318 subtype = (xmlSchemaTypePtr)
4319 xmlSchemaParseElement(ctxt, schema, child, 0);
4320 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004321 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004322 } else if (IS_SCHEMA(child, "any")) {
4323 subtype = xmlSchemaParseAny(ctxt, schema, child);
4324 } else if (IS_SCHEMA(child, "sequence")) {
4325 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4326 } else if (IS_SCHEMA(child, "choice")) {
4327 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4328 }
4329 if (subtype != NULL) {
4330 if (last == NULL) {
4331 type->subtypes = subtype;
4332 last = subtype;
4333 } else {
4334 last->next = subtype;
4335 last = subtype;
4336 }
4337 last->next = NULL;
4338 }
4339 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004340 }
4341 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
4343 "Choice %s has unexpected content\n", type->name,
4344 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 }
4346
4347 return (type);
4348}
4349
4350/**
4351 * xmlSchemaParseSequence:
4352 * @ctxt: a schema validation context
4353 * @schema: the schema being built
4354 * @node: a subtree containing XML Schema informations
4355 *
4356 * parse a XML schema Sequence definition
4357 * *WARNING* this interface is highly subject to change
4358 *
William M. Bracke7091952004-05-11 15:09:58 +00004359 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 * 1 in case of success.
4361 */
4362static xmlSchemaTypePtr
4363xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004364 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004365{
4366 xmlSchemaTypePtr type, subtype, last = NULL;
4367 xmlNodePtr child = NULL;
4368 xmlChar name[30];
4369
4370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4371 return (NULL);
4372
4373
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004375 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004376 if (type == NULL)
4377 return (NULL);
4378 type->node = node;
4379 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004380 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4382 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
4383
4384 child = node->children;
4385 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004386 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4387 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004388 }
4389 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004390 (IS_SCHEMA(child, "group")) ||
4391 (IS_SCHEMA(child, "any")) ||
4392 (IS_SCHEMA(child, "choice")) ||
4393 (IS_SCHEMA(child, "sequence"))) {
4394 subtype = NULL;
4395 if (IS_SCHEMA(child, "element")) {
4396 subtype = (xmlSchemaTypePtr)
4397 xmlSchemaParseElement(ctxt, schema, child, 0);
4398 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004399 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004400 } else if (IS_SCHEMA(child, "any")) {
4401 subtype = xmlSchemaParseAny(ctxt, schema, child);
4402 } else if (IS_SCHEMA(child, "choice")) {
4403 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4404 } else if (IS_SCHEMA(child, "sequence")) {
4405 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4406 }
4407 if (subtype != NULL) {
4408 if (last == NULL) {
4409 type->subtypes = subtype;
4410 last = subtype;
4411 } else {
4412 last->next = subtype;
4413 last = subtype;
4414 }
4415 last->next = NULL;
4416 }
4417 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 }
4419 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004420 xmlSchemaPErr2(ctxt, node, child,
4421 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4422 "Sequence %s has unexpected content\n", type->name,
4423 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004424 }
4425
4426 return (type);
4427}
4428
4429/**
4430 * xmlSchemaParseRestriction:
4431 * @ctxt: a schema validation context
4432 * @schema: the schema being built
4433 * @node: a subtree containing XML Schema informations
4434 * @simple: is that part of a simple type.
4435 *
4436 * parse a XML schema Restriction definition
4437 * *WARNING* this interface is highly subject to change
4438 *
4439 * Returns the type definition or NULL in case of error
4440 */
4441static xmlSchemaTypePtr
4442xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4443 xmlNodePtr node, int simple)
4444{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004445 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 xmlNodePtr child = NULL;
4447 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004448 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004449
4450 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4451 return (NULL);
4452
4453 oldcontainer = ctxt->container;
4454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004455 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004456 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004457 if (type == NULL)
4458 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004459 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00004460 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004461 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004462 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00004463 if ((type->base == NULL) &&
4464 (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004465 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00004466 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
4467 "Restriction \"%s\" must have a \"base\" attribute.\n",
4468 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 }
4470 ctxt->container = name;
4471
4472 child = node->children;
4473 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004474 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4475 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 }
4477 subtype = NULL;
4478
Daniel Veillard01fa6152004-06-29 17:04:39 +00004479 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
4480 if (IS_SCHEMA(child, "all")) {
4481 subtype = (xmlSchemaTypePtr)
4482 xmlSchemaParseAll(ctxt, schema, child);
4483 child = child->next;
4484 type->subtypes = subtype;
4485 } else if (IS_SCHEMA(child, "choice")) {
4486 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4487 child = child->next;
4488 type->subtypes = subtype;
4489 } else if (IS_SCHEMA(child, "sequence")) {
4490 subtype = (xmlSchemaTypePtr)
4491 xmlSchemaParseSequence(ctxt, schema, child);
4492 child = child->next;
4493 type->subtypes = subtype;
4494 } else if (IS_SCHEMA(child, "group")) {
4495 subtype = (xmlSchemaTypePtr)
4496 xmlSchemaParseGroup(ctxt, schema, child, 0);
4497 child = child->next;
4498 type->subtypes = subtype;
4499 }
4500 } else if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
4501 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
4502 xmlSchemaFacetPtr facet, lastfacet = NULL;
4503
4504 if (IS_SCHEMA(child, "simpleType")) {
4505 subtype = (xmlSchemaTypePtr)
4506 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4507 /*
4508 * For the simple type this serves as the base type.
4509 */
4510 type->baseType = subtype;
4511 /*
4512 * For the complex type this serves as information for the
4513 * definition of the content type.
4514 * Additionally this is a hack for the simple type, to save
4515 * the information that a local simple type was defined; thus
4516 * allowing to check: src-restriction-base-or-simpleType.
4517 */
4518 type->subtypes = subtype;
4519 child = child->next;
4520 }
4521 /*
4522 * Add the facets to the parent simpleType/complexType.
4523 */
4524 while ((IS_SCHEMA(child, "minInclusive")) ||
4525 (IS_SCHEMA(child, "minExclusive")) ||
4526 (IS_SCHEMA(child, "maxInclusive")) ||
4527 (IS_SCHEMA(child, "maxExclusive")) ||
4528 (IS_SCHEMA(child, "totalDigits")) ||
4529 (IS_SCHEMA(child, "fractionDigits")) ||
4530 (IS_SCHEMA(child, "pattern")) ||
4531 (IS_SCHEMA(child, "enumeration")) ||
4532 (IS_SCHEMA(child, "whiteSpace")) ||
4533 (IS_SCHEMA(child, "length")) ||
4534 (IS_SCHEMA(child, "maxLength")) ||
4535 (IS_SCHEMA(child, "minLength"))) {
4536 facet = xmlSchemaParseFacet(ctxt, schema, child);
4537 if (facet != NULL) {
4538 if (lastfacet == NULL)
4539 ctxt->ctxtType->facets = facet;
4540 else
4541 lastfacet->next = facet;
4542 lastfacet = facet;
4543 lastfacet->next = NULL;
4544 }
4545 child = child->next;
4546 }
4547 /*
4548 * Create links for derivation and validation.
4549 */
4550 if (lastfacet != NULL) {
4551 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
4552
4553 facet = ctxt->ctxtType->facets;
4554 do {
4555 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
4556 if (facetLink == NULL) {
4557 xmlSchemaPErrMemory(ctxt, "allocation a facet link", NULL);
4558 xmlFree(facetLink);
4559 return (NULL);
4560 }
4561 facetLink->facet = facet;
4562 facetLink->next = NULL;
4563 if (lastFacetLink == NULL)
4564 ctxt->ctxtType->facetSet = facetLink;
4565 else
4566 lastFacetLink->next = facetLink;
4567 lastFacetLink = facetLink;
4568 facet = facet->next;
4569 } while (facet != NULL);
4570 }
4571 }
4572 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
4573 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004575 xmlSchemaPErr2(ctxt, node, child,
4576 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
4577 "Restriction \"%s\" has unexpected content.\n",
4578 type->name, NULL);
4579 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004580 ctxt->container = oldcontainer;
4581 return (type);
4582}
4583
4584/**
4585 * xmlSchemaParseExtension:
4586 * @ctxt: a schema validation context
4587 * @schema: the schema being built
4588 * @node: a subtree containing XML Schema informations
4589 *
4590 * parse a XML schema Extension definition
4591 * *WARNING* this interface is highly subject to change
4592 *
4593 * Returns the type definition or NULL in case of error
4594 */
4595static xmlSchemaTypePtr
4596xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004598{
4599 xmlSchemaTypePtr type, subtype;
4600 xmlNodePtr child = NULL;
4601 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004602 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00004603
4604 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4605 return (NULL);
4606
4607 oldcontainer = ctxt->container;
4608
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004609 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004610 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004611 if (type == NULL)
4612 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004613 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00004614 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004615 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004616 ctxt->container = name;
4617
4618 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
4619 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004620 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
4621 "Extension %s has no base\n", type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 }
4623 child = node->children;
4624 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4626 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004627 }
4628 subtype = NULL;
4629
4630 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 subtype = xmlSchemaParseAll(ctxt, schema, child);
4632 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004633 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004634 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4635 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004636 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4638 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004639 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004640 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004642 }
4643 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004644 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00004645 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
4646 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 xmlSchemaPErr2(ctxt, node, child,
4648 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
4649 "Extension %s has unexpected content\n", type->name,
4650 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004651 }
4652 ctxt->container = oldcontainer;
4653 return (type);
4654}
4655
4656/**
4657 * xmlSchemaParseSimpleContent:
4658 * @ctxt: a schema validation context
4659 * @schema: the schema being built
4660 * @node: a subtree containing XML Schema informations
4661 *
4662 * parse a XML schema SimpleContent definition
4663 * *WARNING* this interface is highly subject to change
4664 *
4665 * Returns the type definition or NULL in case of error
4666 */
4667static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004668xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
4669 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004670{
4671 xmlSchemaTypePtr type, subtype;
4672 xmlNodePtr child = NULL;
4673 xmlChar name[30];
4674
4675 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4676 return (NULL);
4677
William M. Bracke7091952004-05-11 15:09:58 +00004678 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004679 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004680 if (type == NULL)
4681 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004682 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00004683 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004684 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004685
4686 child = node->children;
4687 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004688 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4689 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004690 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004691 ctxt->parentItem = type;
4692 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004693 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004694 subtype = (xmlSchemaTypePtr)
4695 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4696 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004697 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004698 subtype = (xmlSchemaTypePtr)
4699 xmlSchemaParseExtension(ctxt, schema, child);
4700 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004701 }
4702 type->subtypes = subtype;
4703 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004704 xmlSchemaPErr2(ctxt, node, child,
4705 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
4706 "SimpleContent %s has unexpected content\n",
4707 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004708 }
4709 return (type);
4710}
4711
4712/**
4713 * xmlSchemaParseComplexContent:
4714 * @ctxt: a schema validation context
4715 * @schema: the schema being built
4716 * @node: a subtree containing XML Schema informations
4717 *
4718 * parse a XML schema ComplexContent definition
4719 * *WARNING* this interface is highly subject to change
4720 *
4721 * Returns the type definition or NULL in case of error
4722 */
4723static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004724xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
4725 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004726{
4727 xmlSchemaTypePtr type, subtype;
4728 xmlNodePtr child = NULL;
4729 xmlChar name[30];
4730
4731 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4732 return (NULL);
4733
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004734 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004735 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004736 if (type == NULL)
4737 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00004738 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004739 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004740 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004741
4742 child = node->children;
4743 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004744 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4745 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004746 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004747 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004748 subtype = NULL;
4749 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004750 subtype = (xmlSchemaTypePtr)
4751 xmlSchemaParseRestriction(ctxt, schema, child, 0);
4752 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004753 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004754 subtype = (xmlSchemaTypePtr)
4755 xmlSchemaParseExtension(ctxt, schema, child);
4756 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004757 }
4758 type->subtypes = subtype;
4759 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004760 xmlSchemaPErr2(ctxt, node, child,
4761 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
4762 "ComplexContent %s has unexpected content\n",
4763 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004764 }
4765 return (type);
4766}
4767
4768/**
4769 * xmlSchemaParseComplexType:
4770 * @ctxt: a schema validation context
4771 * @schema: the schema being built
4772 * @node: a subtree containing XML Schema informations
4773 *
4774 * parse a XML schema Complex Type definition
4775 * *WARNING* this interface is highly subject to change
4776 *
4777 * Returns the type definition or NULL in case of error
4778 */
4779static xmlSchemaTypePtr
4780xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004781 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004782{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004783 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004784 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004785 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00004786 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004787 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004788
4789 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4790 return (NULL);
4791
Daniel Veillard01fa6152004-06-29 17:04:39 +00004792 ctxtType = ctxt->ctxtType;
4793
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004795 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004796 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00004797 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004798 name = (const xmlChar *)buf;
4799 type = xmlSchemaAddType(ctxt, schema, name, NULL);
4800 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004801
William M. Bracke7091952004-05-11 15:09:58 +00004802 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
4803 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004805 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 return (NULL);
4807 }
William M. Bracke7091952004-05-11 15:09:58 +00004808 if (xmlGetBooleanProp(ctxt, node, "mixed", 0))
4809 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00004810
Daniel Veillard4255d502002-04-16 15:50:10 +00004811 type->node = node;
4812 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00004813 if (topLevel)
4814 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004815 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 ctxt->container = name;
4817
4818 child = node->children;
4819 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4821 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004822 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004823 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00004824 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00004825 /* 3.4.3 : 2.2
4826 * Specifying mixed='true' when the <simpleContent>
4827 * alternative is chosen has no effect
4828 */
4829 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
4830 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
4832 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004833 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004834 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
4835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004836 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004837 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004838
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 if (IS_SCHEMA(child, "all")) {
4840 subtype = xmlSchemaParseAll(ctxt, schema, child);
4841 child = child->next;
4842 } else if (IS_SCHEMA(child, "choice")) {
4843 subtype = xmlSchemaParseChoice(ctxt, schema, child);
4844 child = child->next;
4845 } else if (IS_SCHEMA(child, "sequence")) {
4846 subtype = xmlSchemaParseSequence(ctxt, schema, child);
4847 child = child->next;
4848 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 child = child->next;
4851 }
4852 if (subtype != NULL)
4853 type->subtypes = subtype;
4854 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 }
4856 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004857 xmlSchemaPErr2(ctxt, node, child,
4858 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
4859 "ComplexType %s has unexpected content\n",
4860 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004861 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004862 if (type->attributeWildcard != NULL)
4863 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00004864 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004865 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00004866 return (type);
4867}
4868
Daniel Veillard4255d502002-04-16 15:50:10 +00004869/**
4870 * xmlSchemaParseSchema:
4871 * @ctxt: a schema validation context
4872 * @node: a subtree containing XML Schema informations
4873 *
4874 * parse a XML schema definition from a node set
4875 * *WARNING* this interface is highly subject to change
4876 *
4877 * Returns the internal XML Schema structure built from the resource or
4878 * NULL in case of error
4879 */
4880static xmlSchemaPtr
4881xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4882{
4883 xmlSchemaPtr schema = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004884 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004885 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004886 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00004887
4888 if ((ctxt == NULL) || (node == NULL))
4889 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004890
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004891 nberrors = ctxt->nberrors;
4892 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004893 if (IS_SCHEMA(node, "schema")) {
4894 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004895 if (schema == NULL)
4896 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897 val = xmlSchemaGetProp(ctxt, node, "targetNamespace");
4898 if (val != NULL) {
4899 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
4900 } else {
4901 schema->targetNamespace = NULL;
4902 }
4903 schema->id = xmlSchemaGetProp(ctxt, node, "id");
4904 schema->version = xmlSchemaGetProp(ctxt, node, "version");
4905 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004906 if (val != NULL) {
4907 if (xmlStrEqual(val, BAD_CAST "qualified"))
4908 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
4909 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4910 xmlSchemaPErr2(ctxt, node, child,
4911 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
4912 "Invalid value %s for elementFormDefault\n",
4913 val, NULL);
4914 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004915 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00004916 /* Removed, since the default value for elementFormDefault
4917 * is "unqualified".
4918 */
4919 /* schema->flags |= XML_SCHEMAS_QUALIF_ELEM; */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004920 }
4921 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 if (val != NULL) {
4923 if (xmlStrEqual(val, BAD_CAST "qualified"))
4924 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
4925 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
4926 xmlSchemaPErr2(ctxt, node, child,
4927 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
4928 "Invalid value %s for attributeFormDefault\n",
4929 val, NULL);
4930 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004931 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004932
Daniel Veillard01fa6152004-06-29 17:04:39 +00004933 val = xmlSchemaGetProp(ctxt, node, "finalDefault");
4934 if (val != NULL) {
4935 if (xmlStrEqual(val, BAD_CAST "#all")) {
4936 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4937 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4938 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4939 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4940 } else {
4941 const xmlChar *end, *cur = val;
4942 xmlChar *item;
4943
4944 do {
4945 while (IS_BLANK_CH(*cur))
4946 cur++;
4947 end = cur;
4948 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4949 end++;
4950 if (end == cur)
4951 break;
4952 item = xmlStrndup(cur, end - cur);
4953 if (xmlStrEqual(item, BAD_CAST "extension")) {
4954 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) == 0)
4955 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
4956 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4957 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) == 0)
4958 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
4959 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4960 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) == 0)
4961 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_LIST;
4962 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4963 if ((schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) == 0)
4964 schema->flags |= XML_SCHEMAS_FINAL_DEFAULT_UNION;
4965 } else {
4966 xmlSchemaPErr(ctxt, node,
4967 XML_SCHEMAS_ERR_INTERNAL,
4968 "Invalid value for the attribute \"finalDefault\".\n",
4969 NULL, NULL);
4970 }
4971 if (item != NULL)
4972 xmlFree(item);
4973 cur = end;
4974 } while (*cur != 0);
4975 }
4976 }
4977
Daniel Veillardbd2904b2003-11-25 15:38:59 +00004978 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
4979 } else {
4980 xmlDocPtr doc;
4981
4982 doc = node->doc;
4983
4984 if ((doc != NULL) && (doc->URL != NULL)) {
4985 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4986 XML_SCHEMAP_NOT_SCHEMA,
4987 "File %s is not a schemas", doc->URL, NULL);
4988 } else {
4989 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
4990 XML_SCHEMAP_NOT_SCHEMA,
4991 "File is not a schemas", NULL, NULL);
4992 }
4993 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004994 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004995 if (ctxt->nberrors != 0) {
4996 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 xmlSchemaFree(schema);
4998 schema = NULL;
4999 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00005000 }
5001 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00005002#ifdef DEBUG
5003 if (schema == NULL)
5004 xmlGenericError(xmlGenericErrorContext,
5005 "xmlSchemaParse() failed\n");
5006#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005007 return (schema);
5008}
5009
5010/************************************************************************
5011 * *
5012 * Validating using Schemas *
5013 * *
5014 ************************************************************************/
5015
5016/************************************************************************
5017 * *
5018 * Reading/Writing Schemas *
5019 * *
5020 ************************************************************************/
5021
5022/**
5023 * xmlSchemaNewParserCtxt:
5024 * @URL: the location of the schema
5025 *
5026 * Create an XML Schemas parse context for that file/resource expected
5027 * to contain an XML Schemas file.
5028 *
5029 * Returns the parser context or NULL in case of error
5030 */
5031xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005032xmlSchemaNewParserCtxt(const char *URL)
5033{
Daniel Veillard4255d502002-04-16 15:50:10 +00005034 xmlSchemaParserCtxtPtr ret;
5035
5036 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005037 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005038
5039 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5040 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
5042 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005043 return (NULL);
5044 }
5045 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005046 ret->dict = xmlDictCreate();
5047 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00005048 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005049 return (ret);
5050}
5051
5052/**
Daniel Veillard6045c902002-10-09 21:13:59 +00005053 * xmlSchemaNewMemParserCtxt:
5054 * @buffer: a pointer to a char array containing the schemas
5055 * @size: the size of the array
5056 *
5057 * Create an XML Schemas parse context for that memory buffer expected
5058 * to contain an XML Schemas file.
5059 *
5060 * Returns the parser context or NULL in case of error
5061 */
5062xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005063xmlSchemaNewMemParserCtxt(const char *buffer, int size)
5064{
Daniel Veillard6045c902002-10-09 21:13:59 +00005065 xmlSchemaParserCtxtPtr ret;
5066
5067 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00005069
5070 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5071 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005072 xmlSchemaPErrMemory(NULL, "allocating schama parser context",
5073 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00005074 return (NULL);
5075 }
5076 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
5077 ret->buffer = buffer;
5078 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00005079 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00005080 return (ret);
5081}
5082
5083/**
Daniel Veillard9d751502003-10-29 13:21:47 +00005084 * xmlSchemaNewDocParserCtxt:
5085 * @doc: a preparsed document tree
5086 *
5087 * Create an XML Schemas parse context for that document.
5088 * NB. The document may be modified during the parsing process.
5089 *
5090 * Returns the parser context or NULL in case of error
5091 */
5092xmlSchemaParserCtxtPtr
5093xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
5094{
5095 xmlSchemaParserCtxtPtr ret;
5096
5097 if (doc == NULL)
5098 return (NULL);
5099
5100 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5101 if (ret == NULL) {
5102 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
5103 NULL);
5104 return (NULL);
5105 }
5106 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
5107 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00005108 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00005109 /* The application has responsibility for the document */
5110 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00005111
5112 return (ret);
5113}
5114
5115/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005116 * xmlSchemaFreeParserCtxt:
5117 * @ctxt: the schema parser context
5118 *
5119 * Free the resources associated to the schema parser context
5120 */
5121void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
5123{
Daniel Veillard4255d502002-04-16 15:50:10 +00005124 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005125 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00005126 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005127 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005128 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 xmlFree(ctxt);
5130}
5131
5132/************************************************************************
5133 * *
5134 * Building the content models *
5135 * *
5136 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137
Daniel Veillard4255d502002-04-16 15:50:10 +00005138/**
5139 * xmlSchemaBuildAContentModel:
5140 * @type: the schema type definition
5141 * @ctxt: the schema parser context
5142 * @name: the element name whose content is being built
5143 *
5144 * Generate the automata sequence needed for that type
5145 */
5146static void
5147xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005148 xmlSchemaParserCtxtPtr ctxt,
5149 const xmlChar * name)
5150{
Daniel Veillard4255d502002-04-16 15:50:10 +00005151 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005152 xmlGenericError(xmlGenericErrorContext,
5153 "Found unexpected type = NULL in %s content model\n",
5154 name);
5155 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 }
5157 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005158 case XML_SCHEMA_TYPE_ANY:
5159 /* TODO : handle the namespace too */
5160 /* TODO : make that a specific transition type */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005161 /* Daniel says: use xmlAutomataNewTransition2 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005162 TODO ctxt->state =
5163 xmlAutomataNewTransition(ctxt->am, ctxt->state, NULL,
5164 BAD_CAST "*", NULL);
5165 break;
5166 case XML_SCHEMA_TYPE_ELEMENT:{
5167 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
Daniel Veillard32370232002-10-16 14:08:14 +00005168
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 /* TODO : handle the namespace too */
5170 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005171
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005172 if (elem->maxOccurs >= UNBOUNDED) {
5173 if (elem->minOccurs > 1) {
5174 xmlAutomataStatePtr tmp;
5175 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005176
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5178 oldstate,
5179 NULL);
5180 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005181
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005182 counter = xmlAutomataNewCounter(ctxt->am,
5183 elem->minOccurs -
5184 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00005185
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005186 if (elem->refDecl != NULL) {
5187 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5188 elem->refDecl,
5189 ctxt,
5190 elem->refDecl->
5191 name);
5192 } else {
5193 ctxt->state =
5194 xmlAutomataNewTransition(ctxt->am,
5195 ctxt->state, NULL,
5196 elem->name, type);
5197 }
5198 tmp = ctxt->state;
5199 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5200 counter);
5201 ctxt->state =
5202 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5203 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00005204
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 } else {
5206 if (elem->refDecl != NULL) {
5207 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5208 elem->refDecl,
5209 ctxt,
5210 elem->refDecl->
5211 name);
5212 } else {
5213 ctxt->state =
5214 xmlAutomataNewTransition(ctxt->am,
5215 ctxt->state, NULL,
5216 elem->name, type);
5217 }
5218 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5219 oldstate);
5220 if (elem->minOccurs == 0) {
5221 /* basically an elem* */
5222 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5223 ctxt->state);
5224 }
5225 }
5226 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
5227 xmlAutomataStatePtr tmp;
5228 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00005229
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005230 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5231 oldstate, NULL);
5232 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00005233
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005234 counter = xmlAutomataNewCounter(ctxt->am,
5235 elem->minOccurs - 1,
5236 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005238 if (elem->refDecl != NULL) {
5239 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5240 elem->refDecl, ctxt,
5241 elem->refDecl->name);
5242 } else {
5243 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5244 ctxt->state,
5245 NULL,
5246 elem->name,
5247 type);
5248 }
5249 tmp = ctxt->state;
5250 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5251 counter);
5252 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
5253 NULL,
5254 counter);
5255 if (elem->minOccurs == 0) {
5256 /* basically an elem? */
5257 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5258 ctxt->state);
5259 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00005260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 } else {
5262 if (elem->refDecl != NULL) {
5263 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
5264 elem->refDecl, ctxt,
5265 elem->refDecl->name);
5266 } else {
5267 ctxt->state = xmlAutomataNewTransition(ctxt->am,
5268 ctxt->state,
5269 NULL,
5270 elem->name,
5271 type);
5272 }
5273 if (elem->minOccurs == 0) {
5274 /* basically an elem? */
5275 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5276 ctxt->state);
5277 }
5278 }
5279 break;
5280 }
5281 case XML_SCHEMA_TYPE_SEQUENCE:{
5282 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005283
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005284 /*
5285 * If max and min occurances are default (1) then
5286 * simply iterate over the subtypes
5287 */
5288 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
5289 subtypes = type->subtypes;
5290 while (subtypes != NULL) {
5291 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5292 subtypes = subtypes->next;
5293 }
5294 } else {
5295 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005296
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005297 if (type->maxOccurs >= UNBOUNDED) {
5298 if (type->minOccurs > 1) {
5299 xmlAutomataStatePtr tmp;
5300 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005301
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005302 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5303 oldstate,
5304 NULL);
5305 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005306
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 counter = xmlAutomataNewCounter(ctxt->am,
5308 type->
5309 minOccurs - 1,
5310 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005311
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005312 subtypes = type->subtypes;
5313 while (subtypes != NULL) {
5314 xmlSchemaBuildAContentModel(subtypes, ctxt,
5315 name);
5316 subtypes = subtypes->next;
5317 }
5318 tmp = ctxt->state;
5319 xmlAutomataNewCountedTrans(ctxt->am, tmp,
5320 oldstate, counter);
5321 ctxt->state =
5322 xmlAutomataNewCounterTrans(ctxt->am, tmp,
5323 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00005324
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005325 } else {
5326 subtypes = type->subtypes;
5327 while (subtypes != NULL) {
5328 xmlSchemaBuildAContentModel(subtypes, ctxt,
5329 name);
5330 subtypes = subtypes->next;
5331 }
5332 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
5333 oldstate);
5334 if (type->minOccurs == 0) {
5335 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5336 ctxt->state);
5337 }
5338 }
5339 } else if ((type->maxOccurs > 1)
5340 || (type->minOccurs > 1)) {
5341 xmlAutomataStatePtr tmp;
5342 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00005343
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
5345 oldstate,
5346 NULL);
5347 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00005348
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005349 counter = xmlAutomataNewCounter(ctxt->am,
5350 type->minOccurs -
5351 1,
5352 type->maxOccurs -
5353 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005354
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005355 subtypes = type->subtypes;
5356 while (subtypes != NULL) {
5357 xmlSchemaBuildAContentModel(subtypes, ctxt,
5358 name);
5359 subtypes = subtypes->next;
5360 }
5361 tmp = ctxt->state;
5362 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
5363 counter);
5364 ctxt->state =
5365 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
5366 counter);
5367 if (type->minOccurs == 0) {
5368 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5369 ctxt->state);
5370 }
Daniel Veillardb509f152002-04-17 16:28:10 +00005371
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 } else {
5373 subtypes = type->subtypes;
5374 while (subtypes != NULL) {
5375 xmlSchemaBuildAContentModel(subtypes, ctxt,
5376 name);
5377 subtypes = subtypes->next;
5378 }
5379 if (type->minOccurs == 0) {
5380 xmlAutomataNewEpsilon(ctxt->am, oldstate,
5381 ctxt->state);
5382 }
5383 }
5384 }
5385 break;
5386 }
5387 case XML_SCHEMA_TYPE_CHOICE:{
5388 xmlSchemaTypePtr subtypes;
5389 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00005390
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005391 start = ctxt->state;
5392 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00005393
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394 /*
5395 * iterate over the subtypes and remerge the end with an
5396 * epsilon transition
5397 */
5398 if (type->maxOccurs == 1) {
5399 subtypes = type->subtypes;
5400 while (subtypes != NULL) {
5401 ctxt->state = start;
5402 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5403 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
5404 subtypes = subtypes->next;
5405 }
5406 } else {
5407 int counter;
5408 xmlAutomataStatePtr hop;
5409 int maxOccurs = type->maxOccurs == UNBOUNDED ?
5410 UNBOUNDED : type->maxOccurs - 1;
5411 int minOccurs =
5412 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00005413
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005414 /*
5415 * use a counter to keep track of the number of transtions
5416 * which went through the choice.
5417 */
5418 counter =
5419 xmlAutomataNewCounter(ctxt->am, minOccurs,
5420 maxOccurs);
5421 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00005422
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005423 subtypes = type->subtypes;
5424 while (subtypes != NULL) {
5425 ctxt->state = start;
5426 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5427 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
5428 subtypes = subtypes->next;
5429 }
5430 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
5431 counter);
5432 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
5433 counter);
5434 }
5435 if (type->minOccurs == 0) {
5436 xmlAutomataNewEpsilon(ctxt->am, start, end);
5437 }
5438 ctxt->state = end;
5439 break;
5440 }
5441 case XML_SCHEMA_TYPE_ALL:{
5442 xmlAutomataStatePtr start;
5443 xmlSchemaTypePtr subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00005444 /*
5445 * Changed, since type in not an xmlSchemaElement here.
5446 */
5447 /* xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type; */
5448 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005449 int lax;
5450
5451 subtypes = type->subtypes;
5452 if (subtypes == NULL)
5453 break;
5454 start = ctxt->state;
5455 while (subtypes != NULL) {
5456 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00005457 /*
5458 * the following 'if' was needed to fix bug 139897
5459 * not quite sure why it only needs to be done for
5460 * elements with a 'ref', but it seems to work ok.
5461 */
5462 if (subtypes->ref != NULL)
5463 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00005464 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005465 /* TODO : handle the namespace too */
5466 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
5467 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
5468 ctxt->state, elem->name, 1,
5469 1, subtypes);
5470 } else {
5471 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
5472 ctxt->state, elem->name,
5473 elem->minOccurs,
5474 elem->maxOccurs,
5475 subtypes);
5476 }
5477 subtypes = subtypes->next;
5478 }
5479 lax = type->minOccurs == 0;
5480 ctxt->state =
5481 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
5482 lax);
5483 break;
5484 }
5485 case XML_SCHEMA_TYPE_RESTRICTION:
5486 if (type->subtypes != NULL)
5487 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5488 break;
5489 case XML_SCHEMA_TYPE_EXTENSION:
5490 if (type->baseType != NULL) {
5491 xmlSchemaTypePtr subtypes;
5492
Daniel Veillardf7627552004-04-22 07:15:40 +00005493 if (type->recurse) {
5494 xmlSchemaPErr(ctxt, type->node,
5495 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
5496 "Schemas: extension type %s is recursive\n",
5497 type->name, NULL);
5498 return;
5499 }
5500 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005501 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00005502 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005503 subtypes = type->subtypes;
5504 while (subtypes != NULL) {
5505 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
5506 subtypes = subtypes->next;
5507 }
5508 } else if (type->subtypes != NULL)
5509 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5510 break;
5511 case XML_SCHEMA_TYPE_GROUP:
5512 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00005513 xmlSchemaTypePtr rgroup;
5514 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005515 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00005516 type->refNs);
5517 if (rgroup == NULL) {
5518 xmlSchemaPErr(ctxt, type->node,
5519 XML_SCHEMAP_UNKNOWN_REF,
5520 "Schemas: group %s reference %s is not found",
5521 name, type->ref);
5522 return;
5523 }
5524 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
5525 break;
5526 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005527 }
5528 case XML_SCHEMA_TYPE_COMPLEX:
5529 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
5530 if (type->subtypes != NULL)
5531 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
5532 break;
5533 default:
5534 xmlGenericError(xmlGenericErrorContext,
5535 "Found unexpected type %d in %s content model\n",
5536 type->type, name);
5537 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005538 }
5539}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005540
Daniel Veillard4255d502002-04-16 15:50:10 +00005541/**
5542 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005543 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00005544 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005545 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00005546 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005547 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00005548 */
5549static void
5550xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005551 xmlSchemaParserCtxtPtr ctxt,
5552 const xmlChar * name)
5553{
Daniel Veillard4255d502002-04-16 15:50:10 +00005554 xmlAutomataStatePtr start;
5555
Daniel Veillard4255d502002-04-16 15:50:10 +00005556 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005557 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005558 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005559 elem->contentType = XML_SCHEMA_CONTENT_ANY;
5560 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00005561 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005562 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005563 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005564 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
5565 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005566 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005567
5568#ifdef DEBUG_CONTENT
5569 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005570 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00005571#endif
5572
Daniel Veillard4255d502002-04-16 15:50:10 +00005573 ctxt->am = xmlNewAutomata();
5574 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575 xmlGenericError(xmlGenericErrorContext,
5576 "Cannot create automata for elem %s\n", name);
5577 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00005578 }
5579 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
5580 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
5581 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00005582 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005583 if (elem->contModel == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005584 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_INTERNAL,
5585 "failed to compile %s content model\n", name, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005586 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005587 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAS_ERR_NOTDETERMINIST,
5588 "Content model of %s is not determinist:\n", name,
5589 NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00005590 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00005591#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005592 xmlGenericError(xmlGenericErrorContext,
5593 "Content model of %s:\n", name);
5594 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005595#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00005596 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005597 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 xmlFreeAutomata(ctxt->am);
5599 ctxt->am = NULL;
5600}
5601
5602/**
5603 * xmlSchemaRefFixupCallback:
5604 * @elem: the schema element context
5605 * @ctxt: the schema parser context
5606 *
5607 * Free the resources associated to the schema parser context
5608 */
5609static void
5610xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005611 xmlSchemaParserCtxtPtr ctxt,
5612 const xmlChar * name,
5613 const xmlChar * context ATTRIBUTE_UNUSED,
5614 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00005615{
5616 if ((ctxt == NULL) || (elem == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005617 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00005618
Daniel Veillard4255d502002-04-16 15:50:10 +00005619 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005620 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005621
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 if (elem->subtypes != NULL) {
5623 xmlSchemaPErr(ctxt, elem->node,
5624 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005625 "Schemas: element %s has both ref and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 name, NULL);
5627 return;
5628 }
Daniel Veillardf2a12832003-11-24 13:04:35 +00005629 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillard4255d502002-04-16 15:50:10 +00005630
5631 if (elemDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005632 xmlSchemaPErr(ctxt, elem->node,
5633 XML_SCHEMAP_SRC_RESOLVE,
5634 "Element \"%s\": the QName \"%s\" of the attribute "
5635 "\"ref\" does not resolve to a schema "
5636 "component.\n",
5637 name, elem->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005638 return;
5639 }
5640 elem->refDecl = elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005641 } else if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 xmlSchemaTypePtr typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005643
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005644 if (elem->subtypes != NULL) {
5645 xmlSchemaPErr(ctxt, elem->node, XML_SCHEMAP_TYPE_AND_SUBTYPE,
Daniel Veillard3646d642004-06-02 19:19:14 +00005646 "Schemas: element %s has both type and subtype\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005647 name, NULL);
5648 return;
5649 }
5650 typeDecl = xmlSchemaGetType(ctxt->schema, elem->namedType,
5651 elem->namedTypeNs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005652
5653 if (typeDecl == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005654 xmlSchemaPErr(ctxt, elem->node,
5655 XML_SCHEMAP_SRC_RESOLVE,
5656 "Element \"%s\": the QName \"%s\" of the attribute "
5657 "\"type\" does not resolve to a schema "
5658 "component.\n", name, elem->namedType);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005659 return;
5660 }
5661 elem->subtypes = typeDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00005662 }
5663}
5664
William M. Bracke7091952004-05-11 15:09:58 +00005665/**
5666 * xmlSchemaParseListRefFixup:
5667 * @type: the schema type definition
5668 * @ctxt: the schema parser context
5669 *
5670 * Fixup of the itemType reference of the list type.
5671 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005672static void
William M. Bracke7091952004-05-11 15:09:58 +00005673xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005674{
5675 /*
5676 * src-list-itemType-or-simpleType
5677 * Either the itemType [attribute] or the <simpleType> [child] of
5678 * the <list> element must be present, but not both.
5679 */
5680 if (((type->base == NULL) &&
5681 (type->subtypes == NULL)) ||
5682 ((type->base != NULL) &&
5683 (type->subtypes != NULL))) {
5684 /*
5685 * src-restriction-base-or-simpleType
5686 * Either the base [attribute] or the simpleType [child] of the
5687 * <restriction> element must be present, but not both.
5688 */
5689 xmlSchemaPErr(ctxt, type->node,
5690 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
5691 "List \"%s\": "
5692 "Either the \"base\" attribute or the <simpleType> child "
5693 "must be present, but not both.\n",
5694 type->name, NULL);
5695 } else if (type->base!= NULL) {
5696 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
5697 if (type->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00005698 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_TYPE,
Daniel Veillard01fa6152004-06-29 17:04:39 +00005699 "List \"%s\" references an unknown item type: \"%s\"\n",
5700 type->name, type->base);
5701 }
5702 }
5703 if ((type->subtypes != NULL) &&
5704 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
5705 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005706}
5707
5708/**
5709 * xmlSchemaParseUnionRefCheck:
5710 * @typeDecl: the schema type definition
5711 * @ctxt: the schema parser context
5712 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005713 * Checks and builds the memberTypes of the union type.
5714 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00005715 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005716static int
William M. Bracke7091952004-05-11 15:09:58 +00005717xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00005718 xmlSchemaParserCtxtPtr ctxt)
5719{
5720 const xmlChar *cur, *end, *prefix, *ncName, *namespace;
5721 xmlChar *tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005722 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
5723 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00005724 xmlNsPtr ns;
5725 int len;
5726
Daniel Veillard01fa6152004-06-29 17:04:39 +00005727 /* 1 If the <union> alternative is chosen, then [Definition:]
5728 * define the explicit members as the type definitions ·resolved·
5729 * to by the items in the ·actual value· of the memberTypes [attribute],
5730 * if any, followed by the type definitions corresponding to the
5731 * <simpleType>s among the [children] of <union>, if any.
5732 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00005733
Daniel Veillard01fa6152004-06-29 17:04:39 +00005734 if (type->type != XML_SCHEMA_TYPE_UNION)
5735 return (-1);
5736 if (ctxt->ctxtType == NULL) {
5737 xmlSchemaPErr(ctxt, type->node,
5738 XML_SCHEMAS_ERR_INTERNAL,
5739 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
5740 "available", NULL, NULL);
5741 return (-1);
5742 }
5743 /*
5744 * src-union-memberTypes-or-simpleTypes
5745 * Either the memberTypes [attribute] of the <union> element must
5746 * be non-empty or there must be at least one simpleType [child].
5747 */
5748 if ((type->base == NULL) &&
5749 (type->subtypes == NULL)) {
5750 /*
5751 * src-restriction-base-or-simpleType
5752 * Either the base [attribute] or the simpleType [child] of the
5753 * <restriction> element must be present, but not both.
5754 */
5755 xmlSchemaPErr(ctxt, type->node,
5756 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
5757 "Union \"%s\": "
5758 "Either the \"memberTypes\" attribute must be non-empty "
5759 "or there must be at least one <simpleType> child.\n",
5760 type->name, NULL);
5761 }
5762
5763 ctxtType = ctxt->ctxtType;
5764 if (type->base != NULL) {
5765 cur = type->base;
5766 do {
5767 while (IS_BLANK_CH(*cur))
5768 cur++;
5769 end = cur;
5770 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5771 end++;
5772 if (end == cur)
5773 break;
5774 tmp = xmlStrndup(cur, end - cur);
5775 ncName = xmlSplitQName3(tmp, &len);
5776 if (ncName != NULL) {
5777 prefix = xmlDictLookup(ctxt->dict, tmp, len);
5778 } else {
5779 prefix = NULL;
5780 ncName = tmp;
5781 }
5782 ns = xmlSearchNs(type->node->doc, type->node, prefix);
5783 if (ns == NULL) {
5784 if (prefix != NULL) {
5785 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_PREFIX_UNDEFINED,
5786 "Union \"%s\": the namespace prefix of member type "
5787 "\"%s\" is undefined\n",
5788 type->name, (const xmlChar *) tmp);
5789 }
5790 namespace = NULL;
5791 } else {
5792 namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5793 }
5794 memberType = xmlSchemaGetType(ctxt->schema, ncName, namespace);
5795 if (memberType == NULL) {
5796 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
5797 "Union \"%s\" references an unknown member type \"%s\".\n",
5798 type->name, (const xmlChar *) tmp);
5799 } else {
5800 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5801 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5802 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5803 if (link == NULL) {
5804 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5805 return (-1);
5806 }
5807 link->type = memberType;
5808 link->next = NULL;
5809 if (lastLink == NULL)
5810 ctxtType->memberTypes = link;
5811 else
5812 lastLink->next = link;
5813 lastLink = link;
5814 }
5815 xmlFree(tmp);
5816 cur = end;
5817 } while (*cur != 0);
5818 }
5819 /*
5820 * Add local simple types,
5821 */
5822 memberType = type->subtypes;
5823 while (memberType != NULL) {
5824 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
5825 xmlSchemaTypeFixup(memberType, ctxt, NULL);
5826 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
5827 if (link == NULL) {
5828 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
5829 return (-1);
5830 }
5831 link->type = memberType;
5832 link->next = NULL;
5833 if (lastLink == NULL)
5834 ctxtType->memberTypes = link;
5835 else
5836 lastLink->next = link;
5837 lastLink = link;
5838 memberType = memberType->next;
5839 }
5840 /*
5841 * The actual value is then formed by replacing any union type
5842 * definition in the ·explicit members· with the members of their
5843 * {member type definitions}, in order.
5844 */
5845 link = ctxtType->memberTypes;
5846 while (link != NULL) {
5847 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
5848 subLink = link->type->memberTypes;
5849 if (subLink != NULL) {
5850 link->type = subLink->type;
5851 if (subLink->next != NULL) {
5852 lastLink = link->next;
5853 subLink = subLink->next;
5854 prevLink = link;
5855 while (subLink != NULL) {
5856 newLink = (xmlSchemaTypeLinkPtr)
5857 xmlMalloc(sizeof(xmlSchemaTypeLink));
5858 if (newLink == NULL) {
5859 xmlSchemaPErrMemory(ctxt, "allocating a type link",
5860 NULL);
5861 return (-1);
5862 }
5863 newLink->type = memberType;
5864 prevLink->next = newLink;
5865 prevLink = newLink;
5866 newLink->next = lastLink;
5867
5868 subLink = subLink->next;
5869 }
5870 }
5871 }
5872 }
5873 link = link->next;
5874 }
5875
5876 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00005877}
5878
Daniel Veillard4255d502002-04-16 15:50:10 +00005879/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005880 * xmlSchemaGetOnymousTypeName:
5881 * @attr: the attribute declaration/use
5882 *
5883 * Returns the name of the attribute; if the attribute
5884 * is a reference, the name of the referenced global type will be returned.
5885 */
5886static const xmlChar *
5887xmlSchemaGetOnymousAttrName(xmlSchemaAttributePtr attr)
5888{
5889 if (attr->ref != NULL)
5890 return(attr->ref);
5891 else
5892 return(attr->name);
5893}
5894
5895/**
5896 * xmlSchemaGetOnymousTargetNsURI:
5897 * @type: the type (element or attribute)
5898 *
5899 * Returns the target namespace URI of the type; if the type is a reference,
5900 * the target namespace of the referenced type will be returned.
5901 */
5902static const xmlChar *
5903xmlSchemaGetOnymousTargetNsURI(xmlSchemaTypePtr type)
5904{
5905 if (type->type == XML_SCHEMA_TYPE_ELEMENT) {
5906 if (type->ref != NULL)
5907 return(((xmlSchemaElementPtr)((xmlSchemaElementPtr)
5908 type)->subtypes)->targetNamespace);
5909 else
5910 return(((xmlSchemaElementPtr) type)->targetNamespace);
5911 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5912 if (type->ref != NULL)
5913 return(((xmlSchemaAttributePtr)((xmlSchemaAttributePtr)
5914 type)->subtypes)->targetNamespace);
5915 else
5916 return(((xmlSchemaAttributePtr) type)->targetNamespace);
5917 } else
5918 return (NULL);
5919}
5920
5921/**
5922 * xmlSchemaIsDerivedFromBuiltInType:
5923 * @ctxt: the schema parser context
5924 * @type: the type definition
5925 * @valType: the value type
5926 *
5927 *
5928 * Returns 1 if the type has the given value type, or
5929 * is derived from such a type.
5930 */
William M. Brack803812b2004-06-03 02:11:24 +00005931static int
Daniel Veillard3646d642004-06-02 19:19:14 +00005932xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
5933 xmlSchemaTypePtr type, int valType)
5934{
5935 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005936 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00005937 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005938 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00005939 return(1);
5940 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
5941 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
5942 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
5943 ((xmlSchemaAttributePtr) type)->subtypes, valType));
5944 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
5945 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
5946 if (type->baseType != NULL)
5947 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
5948 valType));
5949 } else if ((type->subtypes != NULL) &&
5950 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
5951 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
5952 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
5953 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
5954 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
5955 valType));
5956 }
5957
5958 return (0);
5959}
5960
5961/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00005962 * xmlSchemaIsDerivedFromBuiltInType:
5963 * @type: the simpleType definition
5964 *
5965 * Returns the primitive type of the given type or
5966 * NULL in case of error.
5967 */
5968static xmlSchemaTypePtr
5969xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
5970{
5971 while (type != NULL) {
5972 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
5973 return (type);
5974 type = type->baseType;
5975 }
5976
5977 return (NULL);
5978}
5979
5980
5981/**
Daniel Veillard3646d642004-06-02 19:19:14 +00005982 * xmlSchemaBuildAttributeUsesOwned:
5983 * @ctxt: the schema parser context
5984 * @type: the complex type definition
5985 * @cur: the attribute declaration list
5986 * @lastUse: the top of the attribute use list
5987 *
5988 * Builds the attribute uses list on the given complex type.
5989 * This one is supposed to be called by
5990 * xmlSchemaBuildAttributeValidation only.
5991 */
5992static int
5993xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
5994 xmlSchemaAttributePtr cur,
5995 xmlSchemaAttributeLinkPtr *uses,
5996 xmlSchemaAttributeLinkPtr *lastUse)
5997{
5998 xmlSchemaAttributeLinkPtr tmp;
5999 while (cur != NULL) {
6000 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6001 /*
6002 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
6003 * to by the ·actual value·s of the ref [attribute] of the
6004 * <attributeGroup> [children], if any."
6005 */
6006 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
6007 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
6008 lastUse) == -1) {
6009 return (-1);
6010 }
6011 } else {
6012 /* W3C: "1 The set of attribute uses corresponding to the
6013 * <attribute> [children], if any."
6014 */
6015 tmp = (xmlSchemaAttributeLinkPtr)
6016 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6017 if (tmp == NULL) {
6018 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
6019 return (-1);
6020 }
6021 tmp->attr = cur;
6022 tmp->next = NULL;
6023 if (*uses == NULL)
6024 *uses = tmp;
6025 else
6026 (*lastUse)->next = tmp;
6027 *lastUse = tmp;
6028 }
6029 cur = cur->next;
6030 }
6031 return (0);
6032}
6033
Daniel Veillard50355f02004-06-08 17:52:16 +00006034/**
6035 * xmlSchemaCloneWildcardNsConstraints:
6036 * @ctxt: the schema parser context
6037 * @dest: the destination wildcard
6038 * @source: the source wildcard
6039 *
6040 * Clones the namespace constraints of source
6041 * and assignes them to dest.
6042 * Returns -1 on internal error, 0 otherwise.
6043 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006044static int
6045xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
6046 xmlSchemaWildcardPtr *dest,
6047 xmlSchemaWildcardPtr source)
6048{
6049 xmlSchemaWildcardNsPtr cur, tmp, last;
6050
6051 if ((source == NULL) || (*dest == NULL))
6052 return(-1);
6053 (*dest)->any = source->any;
6054 cur = source->nsSet;
6055 last = NULL;
6056 while (cur != NULL) {
6057 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6058 if (tmp == NULL)
6059 return(-1);
6060 tmp->value = cur->value;
6061 if (last == NULL)
6062 (*dest)->nsSet = tmp;
6063 else
6064 last->next = tmp;
6065 last = tmp;
6066 cur = cur->next;
6067 }
6068 if ((*dest)->negNsSet != NULL)
6069 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
6070 if (source->negNsSet != NULL) {
6071 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6072 if ((*dest)->negNsSet == NULL)
6073 return(-1);
6074 (*dest)->negNsSet->value = source->negNsSet->value;
6075 } else
6076 (*dest)->negNsSet = NULL;
6077 return(0);
6078}
6079
Daniel Veillard50355f02004-06-08 17:52:16 +00006080/**
6081 * xmlSchemaUnionWildcards:
6082 * @ctxt: the schema parser context
6083 * @completeWild: the first wildcard
6084 * @curWild: the second wildcard
6085 *
6086 * Unions the namespace constraints of the given wildcards.
6087 * @completeWild will hold the resulting union.
6088 * Returns a positive error code on failure, -1 in case of an
6089 * internal error, 0 otherwise.
6090 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006091static int
6092xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
6093 xmlSchemaWildcardPtr completeWild,
6094 xmlSchemaWildcardPtr curWild)
6095{
6096 xmlSchemaWildcardNsPtr cur, curB, tmp;
6097
6098 /*
6099 * 1 If O1 and O2 are the same value, then that value must be the
6100 * value.
6101 */
6102 if ((completeWild->any == curWild->any) &&
6103 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
6104 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
6105
6106 if ((completeWild->negNsSet == NULL) ||
6107 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
6108
6109 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00006110 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006111
6112 /*
6113 * Check equality of sets.
6114 */
6115 cur = completeWild->nsSet;
6116 while (cur != NULL) {
6117 found = 0;
6118 curB = curWild->nsSet;
6119 while (curB != NULL) {
6120 if (cur->value == curB->value) {
6121 found = 1;
6122 break;
6123 }
6124 curB = curB->next;
6125 }
6126 if (!found)
6127 break;
6128 cur = cur->next;
6129 }
6130 if (found)
6131 return(0);
6132 } else
6133 return(0);
6134 }
6135 }
6136 /*
6137 * 2 If either O1 or O2 is any, then any must be the value
6138 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006139 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006140 if (completeWild->any == 0) {
6141 completeWild->any = 1;
6142 if (completeWild->nsSet != NULL) {
6143 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6144 completeWild->nsSet = NULL;
6145 }
6146 if (completeWild->negNsSet != NULL) {
6147 xmlFree(completeWild->negNsSet);
6148 completeWild->negNsSet = NULL;
6149 }
6150 }
Daniel Veillard50355f02004-06-08 17:52:16 +00006151 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006152 }
6153 /*
6154 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
6155 * then the union of those sets must be the value.
6156 */
6157 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
6158 int found;
6159 xmlSchemaWildcardNsPtr start;
6160
6161 cur = curWild->nsSet;
6162 start = completeWild->nsSet;
6163 while (cur != NULL) {
6164 found = 0;
6165 curB = start;
6166 while (curB != NULL) {
6167 if (cur->value == curB->value) {
6168 found = 1;
6169 break;
6170 }
6171 curB = curB->next;
6172 }
6173 if (!found) {
6174 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6175 if (tmp == NULL)
6176 return (-1);
6177 tmp->value = cur->value;
6178 tmp->next = completeWild->nsSet;
6179 completeWild->nsSet = tmp;
6180 }
6181 cur = cur->next;
6182 }
6183
6184 return(0);
6185 }
6186 /*
6187 * 4 If the two are negations of different values (namespace names
6188 * or ·absent·), then a pair of not and ·absent· must be the value.
6189 */
6190 if ((completeWild->negNsSet != NULL) &&
6191 (curWild->negNsSet != NULL) &&
6192 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
6193 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00006194
6195 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006196 }
6197 /*
6198 * 5.
6199 */
6200 if (((completeWild->negNsSet != NULL) &&
6201 (completeWild->negNsSet->value != NULL) &&
6202 (curWild->nsSet != NULL)) ||
6203 ((curWild->negNsSet != NULL) &&
6204 (curWild->negNsSet->value != NULL) &&
6205 (completeWild->nsSet != NULL))) {
6206
6207 int nsFound, absentFound = 0;
6208
6209 if (completeWild->nsSet != NULL) {
6210 cur = completeWild->nsSet;
6211 curB = curWild->negNsSet;
6212 } else {
6213 cur = curWild->nsSet;
6214 curB = completeWild->negNsSet;
6215 }
6216 nsFound = 0;
6217 while (cur != NULL) {
6218 if (cur->value == NULL)
6219 absentFound = 1;
6220 else if (cur->value == curB->value)
6221 nsFound = 1;
6222 if (nsFound && absentFound)
6223 break;
6224 cur = cur->next;
6225 }
6226
6227 if (nsFound && absentFound) {
6228 /*
6229 * 5.1 If the set S includes both the negated namespace
6230 * name and ·absent·, then any must be the value.
6231 */
6232 completeWild->any = 1;
6233 if (completeWild->nsSet != NULL) {
6234 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6235 completeWild->nsSet = NULL;
6236 }
6237 if (completeWild->negNsSet != NULL) {
6238 xmlFree(completeWild->negNsSet);
6239 completeWild->negNsSet = NULL;
6240 }
6241 } else if (nsFound && (!absentFound)) {
6242 /*
6243 * 5.2 If the set S includes the negated namespace name
6244 * but not ·absent·, then a pair of not and ·absent· must
6245 * be the value.
6246 */
6247 if (completeWild->nsSet != NULL) {
6248 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6249 completeWild->nsSet = NULL;
6250 }
6251 if (completeWild->negNsSet == NULL) {
6252 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6253 if (completeWild->negNsSet == NULL)
6254 return (-1);
6255 }
6256 completeWild->negNsSet->value = NULL;
6257 } else if ((!nsFound) && absentFound) {
6258 /*
6259 * 5.3 If the set S includes ·absent· but not the negated
6260 * namespace name, then the union is not expressible.
6261 */
6262 xmlSchemaPErr(ctxt, completeWild->node,
6263 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
6264 "The union of the wilcard is not expressible\n",
6265 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006266 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006267 } else if ((!nsFound) && (!absentFound)) {
6268 /*
6269 * 5.4 If the set S does not include either the negated namespace
6270 * name or ·absent·, then whichever of O1 or O2 is a pair of not
6271 * and a namespace name must be the value.
6272 */
6273 if (completeWild->negNsSet == NULL) {
6274 if (completeWild->nsSet != NULL) {
6275 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6276 completeWild->nsSet = NULL;
6277 }
6278 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6279 if (completeWild->negNsSet == NULL)
6280 return (-1);
6281 completeWild->negNsSet->value = curWild->negNsSet->value;
6282 }
6283 }
6284 return (0);
6285 }
6286 /*
6287 * 6.
6288 */
6289 if (((completeWild->negNsSet != NULL) &&
6290 (completeWild->negNsSet->value == NULL) &&
6291 (curWild->nsSet != NULL)) ||
6292 ((curWild->negNsSet != NULL) &&
6293 (curWild->negNsSet->value == NULL) &&
6294 (completeWild->nsSet != NULL))) {
6295
6296 if (completeWild->nsSet != NULL) {
6297 cur = completeWild->nsSet;
6298 } else {
6299 cur = curWild->nsSet;
6300 }
6301 while (cur != NULL) {
6302 if (cur->value == NULL) {
6303 /*
6304 * 6.1 If the set S includes ·absent·, then any must be the
6305 * value.
6306 */
6307 completeWild->any = 1;
6308 if (completeWild->nsSet != NULL) {
6309 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6310 completeWild->nsSet = NULL;
6311 }
6312 if (completeWild->negNsSet != NULL) {
6313 xmlFree(completeWild->negNsSet);
6314 completeWild->negNsSet = NULL;
6315 }
6316 return (0);
6317 }
6318 cur = cur->next;
6319 }
6320 if (completeWild->negNsSet == NULL) {
6321 /*
6322 * 6.2 If the set S does not include ·absent·, then a pair of not
6323 * and ·absent· must be the value.
6324 */
6325 if (completeWild->nsSet != NULL) {
6326 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
6327 completeWild->nsSet = NULL;
6328 }
6329 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6330 if (completeWild->negNsSet == NULL)
6331 return (-1);
6332 completeWild->negNsSet->value = NULL;
6333 }
6334 return (0);
6335 }
6336 return (0);
6337
6338}
6339
Daniel Veillard50355f02004-06-08 17:52:16 +00006340/**
6341 * xmlSchemaIntersectWildcards:
6342 * @ctxt: the schema parser context
6343 * @completeWild: the first wildcard
6344 * @curWild: the second wildcard
6345 *
6346 * Intersects the namespace constraints of the given wildcards.
6347 * @completeWild will hold the resulting intersection.
6348 * Returns a positive error code on failure, -1 in case of an
6349 * internal error, 0 otherwise.
6350 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006351static int
6352xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
6353 xmlSchemaWildcardPtr completeWild,
6354 xmlSchemaWildcardPtr curWild)
6355{
William M. Brack803812b2004-06-03 02:11:24 +00006356 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00006357
6358 /*
6359 * 1 If O1 and O2 are the same value, then that value must be the
6360 * value.
6361 */
6362 if ((completeWild->any == curWild->any) &&
6363 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
6364 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
6365
6366 if ((completeWild->negNsSet == NULL) ||
6367 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
6368
6369 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00006370 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006371
6372 /*
6373 * Check equality of sets.
6374 */
6375 cur = completeWild->nsSet;
6376 while (cur != NULL) {
6377 found = 0;
6378 curB = curWild->nsSet;
6379 while (curB != NULL) {
6380 if (cur->value == curB->value) {
6381 found = 1;
6382 break;
6383 }
6384 curB = curB->next;
6385 }
6386 if (!found)
6387 break;
6388 cur = cur->next;
6389 }
6390 if (found)
6391 return(0);
6392 } else
6393 return(0);
6394 }
6395 }
6396 /*
6397 * 2 If either O1 or O2 is any, then the other must be the value.
6398 */
6399 if ((completeWild->any != curWild->any) && (completeWild->any)) {
6400 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6401 return(-1);
6402 return(0);
6403 }
6404 /*
6405 * 3 If either O1 or O2 is a pair of not and a value (a namespace
6406 * name or ·absent·) and the other is a set of (namespace names or
6407 * ·absent·), then that set, minus the negated value if it was in
6408 * the set, minus ·absent· if it was in the set, must be the value.
6409 */
6410 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
6411 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
6412 const xmlChar *neg;
6413
6414 if (completeWild->nsSet == NULL) {
6415 neg = completeWild->negNsSet->value;
6416 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
6417 return(-1);
6418 } else
6419 neg = curWild->negNsSet->value;
6420 /*
6421 * Remove absent and negated.
6422 */
6423 prev = NULL;
6424 cur = completeWild->nsSet;
6425 while (cur != NULL) {
6426 if (cur->value == NULL) {
6427 if (prev == NULL)
6428 completeWild->nsSet = cur->next;
6429 else
6430 prev->next = cur->next;
6431 xmlFree(cur);
6432 break;
6433 }
6434 prev = cur;
6435 cur = cur->next;
6436 }
6437 if (neg != NULL) {
6438 prev = NULL;
6439 cur = completeWild->nsSet;
6440 while (cur != NULL) {
6441 if (cur->value == neg) {
6442 if (prev == NULL)
6443 completeWild->nsSet = cur->next;
6444 else
6445 prev->next = cur->next;
6446 xmlFree(cur);
6447 break;
6448 }
6449 prev = cur;
6450 cur = cur->next;
6451 }
6452 }
6453
6454 return(0);
6455 }
6456 /*
6457 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
6458 * then the intersection of those sets must be the value.
6459 */
6460 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
6461 int found;
6462
6463 cur = completeWild->nsSet;
6464 prev = NULL;
6465 while (cur != NULL) {
6466 found = 0;
6467 curB = curWild->nsSet;
6468 while (curB != NULL) {
6469 if (cur->value == curB->value) {
6470 found = 1;
6471 break;
6472 }
6473 curB = curB->next;
6474 }
6475 if (!found) {
6476 if (prev == NULL)
6477 completeWild->nsSet = cur->next;
6478 else
6479 prev->next = cur->next;
6480 tmp = cur->next;
6481 xmlFree(cur);
6482 cur = tmp;
6483 continue;
6484 }
6485 prev = cur;
6486 cur = cur->next;
6487 }
6488
6489 return(0);
6490 }
6491 /* 5 If the two are negations of different namespace names,
6492 * then the intersection is not expressible
6493 */
6494 if ((completeWild->negNsSet != NULL) &&
6495 (curWild->negNsSet != NULL) &&
6496 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6497 (completeWild->negNsSet->value != NULL) &&
6498 (curWild->negNsSet->value != NULL)) {
6499
6500 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
6501 "The intersection of the wilcard is not expressible\n",
6502 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00006503 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006504 }
6505 /*
6506 * 6 If the one is a negation of a namespace name and the other
6507 * is a negation of ·absent·, then the one which is the negation
6508 * of a namespace name must be the value.
6509 */
6510 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
6511 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
6512 (completeWild->negNsSet->value == NULL)) {
6513 completeWild->negNsSet->value = curWild->negNsSet->value;
6514 }
6515 return(0);
6516}
6517
Daniel Veillard50355f02004-06-08 17:52:16 +00006518/**
6519 * xmlSchemaIsWildcardNsConstraintSubset:
6520 * @ctxt: the schema parser context
6521 * @wildA: the first wildcard
6522 * @wildB: the second wildcard
6523 *
6524 * Returns 1 if the namespace constraint of @wildA is an intensional
6525 * subset of @wildB, 0 otherwise.
6526 */
6527static int
6528xmlSchemaIsWildcardNsConstraintSubset(
6529 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
6530 xmlSchemaWildcardPtr wildA,
6531 xmlSchemaWildcardPtr wildB)
6532{
Daniel Veillard3646d642004-06-02 19:19:14 +00006533
Daniel Veillard50355f02004-06-08 17:52:16 +00006534 /*
6535 * Schema Component Constraint: Wildcard Subset
6536 */
6537 /*
6538 * 1 super must be any.
6539 */
6540 if (wildB->any)
6541 return (1);
6542 /*
6543 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
6544 * 2.2 super must be a pair of not and the same value.
6545 */
6546 if ((wildA->negNsSet != NULL) &&
6547 (wildB->negNsSet != NULL) &&
6548 (wildA->negNsSet->value == wildA->negNsSet->value))
6549 return (1);
6550 /*
6551 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
6552 */
6553 if (wildA->nsSet != NULL) {
6554 /*
6555 * 3.2.1 super must be the same set or a superset thereof.
6556 */
6557 if (wildB->nsSet != NULL) {
6558 xmlSchemaWildcardNsPtr cur, curB;
6559 int found = 0;
6560
6561 cur = wildA->nsSet;
6562 while (cur != NULL) {
6563 found = 0;
6564 curB = wildB->nsSet;
6565 while (curB != NULL) {
6566 if (cur->value == curB->value) {
6567 found = 1;
6568 break;
6569 }
6570 curB = curB->next;
6571 }
6572 if (!found)
6573 return (0);
6574 cur = cur->next;
6575 }
6576 if (found)
6577 return (1);
6578 } else if (wildB->negNsSet != NULL) {
6579 xmlSchemaWildcardNsPtr cur;
6580 /*
6581 * 3.2.2 super must be a pair of not and a namespace name or
6582 * ·absent· and that value must not be in sub's set.
6583 */
6584 cur = wildA->nsSet;
6585 while (cur != NULL) {
6586 if (cur->value == wildB->negNsSet->value)
6587 return (0);
6588 cur = cur->next;
6589 }
6590 return (1);
6591 }
6592 }
6593 return (0);
6594}
6595
6596/**
6597 * xmlSchemaBuildCompleteAttributeWildcard:
6598 * @ctxt: the schema parser context
6599 * @attrs: the attribute list
6600 * @completeWild: the resulting complete wildcard
6601 *
6602 * Returns -1 in case of an internal error, 0 otherwise.
6603 */
6604static int
6605xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
6606 xmlSchemaAttributePtr attrs,
6607 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00006608{
6609 while (attrs != NULL) {
6610 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
6611 xmlSchemaAttributeGroupPtr group;
6612
6613 group = (xmlSchemaAttributeGroupPtr) attrs;
6614 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
6615 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006616 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6617 group->attributes, &group->attributeWildcard) == -1)
6618 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006619 }
6620 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
6621 }
6622 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006623 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006624 /*
6625 * Copy the first encountered wildcard as context, except for the annotation.
6626 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006627 *completeWild = xmlSchemaAddWildcard(ctxt);
6628 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
6629 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
6630 completeWild, group->attributeWildcard) == -1)
6631 return (-1);
6632 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00006633 /*
6634 * Although the complete wildcard might not correspond to any
6635 * node in the schema, we will save this context node.
6636 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006637 (*completeWild)->node = group->attributeWildcard->node;
6638
6639 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
6640 xmlSchemaFreeWildcard(*completeWild);
6641 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00006642 }
6643 }
6644 }
6645 attrs = attrs->next;
6646 }
6647
Daniel Veillard50355f02004-06-08 17:52:16 +00006648 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00006649}
6650
6651/**
6652 * xmlSchemaMatchesWildcardNs:
6653 * @wild: the wildcard
6654 * @ns: the namespace
6655 *
6656 *
6657 * Returns 1 if the given namespace matches the wildcard,
6658 * 0 otherwise.
6659 */
6660static int
6661xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
6662{
6663 if (wild == NULL)
6664 return(0);
6665
6666 if (wild->any)
6667 return(1);
6668 else if (wild->nsSet != NULL) {
6669 xmlSchemaWildcardNsPtr cur;
6670
6671 cur = wild->nsSet;
6672 while (cur != NULL) {
6673 if (xmlStrEqual(cur->value, ns))
6674 return(1);
6675 cur = cur->next;
6676 }
6677 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
6678 (!xmlStrEqual(wild->negNsSet->value, ns)))
6679 return(1);
6680
6681 return(0);
6682}
6683
6684/**
6685 * xmlSchemaBuildAttributeValidation:
6686 * @ctxt: the schema parser context
6687 * @type: the complex type definition
6688 *
6689 *
6690 * Builds the wildcard and the attribute uses on the given complex type.
6691 * Returns -1 if an internal error occurs, 0 otherwise.
6692 */
6693static int
6694xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
6695{
6696 xmlSchemaTypePtr baseType = NULL;
6697 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00006698 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00006699 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006700 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00006701 int baseIsAnyType = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00006702
Daniel Veillard01fa6152004-06-29 17:04:39 +00006703 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00006704 /*
6705 * Complex Type Definition with complex content Schema Component.
6706 *
6707 * Attribute uses.
6708 */
6709 if (type->attributeUses != NULL) {
6710 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006711 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00006712 "attribute uses already builded.\n",
6713 NULL, NULL);
6714 return (-1);
6715 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006716 if (type->baseType == NULL) {
6717 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6718 "Internal error: xmlSchemaBuildAttributeValidation: "
6719 "complex type \"%s\" has no base type.\n",
6720 type->name, NULL);
6721 return (-1);
6722 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006723 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) ||
6724 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006725
6726 baseType = type->baseType;
6727 if (baseType == NULL) {
6728 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
6729 "Internal error: xmlSchemaBuildAttributeValidation: "
6730 "type has no base type.\n",
6731 NULL, NULL);
6732 return (-1);
6733 }
6734
6735 if (baseType == anyType)
6736 baseIsAnyType = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00006737 /*
6738 * Inherit the attribute uses of the base type.
6739 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006740 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +00006741 * NOTE: It is allowed to "extend" the anyType complex type.
Daniel Veillard3646d642004-06-02 19:19:14 +00006742 */
6743 if (!baseIsAnyType) {
6744 if (baseType != NULL) {
6745 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
6746 tmp = (xmlSchemaAttributeLinkPtr)
6747 xmlMalloc(sizeof(xmlSchemaAttributeLink));
6748 if (tmp == NULL) {
6749 xmlSchemaPErrMemory(ctxt,
6750 "building attribute uses of complexType", NULL);
6751 return (-1);
6752 }
6753 tmp->attr = cur->attr;
6754 tmp->next = NULL;
6755 if (type->attributeUses == NULL) {
6756 type->attributeUses = tmp;
6757 } else
6758 lastBaseUse->next = tmp;
6759 lastBaseUse = tmp;
6760 }
6761 }
6762 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006763 if ((type->subtypes != NULL) &&
6764 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
6765 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
6766 attrs = type->subtypes->subtypes->attributes;
6767 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
6768 } else {
6769 /* Short hand form of the complexType. */
6770 attrs = type->attributes;
6771 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006772 /*
6773 * Handle attribute wildcards.
Daniel Veillard50355f02004-06-08 17:52:16 +00006774 */
Daniel Veillard50355f02004-06-08 17:52:16 +00006775 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006776 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard50355f02004-06-08 17:52:16 +00006777 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006778 /* Either we used the short hand form... */
6779 ((type->subtypes == NULL) ||
6780 /* Or complexType -> restriction/extension */
6781 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard50355f02004-06-08 17:52:16 +00006782 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6783 return (-1);
6784 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006785 /*
6786 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
6787 * create the wildcard right from the start on the complexType,
6788 * rather than on the <restriction>/<extension>.
6789 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006790 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006791 /* Either we used the short hand form... */
6792 ((type->subtypes == NULL) ||
6793 /* Or complexType -> restriction/extension */
6794 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00006795 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6796
6797 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00006798 ((baseIsAnyType) ||
6799 ((baseType != NULL) &&
6800 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
6801 (baseType->attributeWildcard != NULL)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006802 if (type->attributeWildcard != NULL) {
6803 /*
6804 * Union the complete wildcard with the base wildcard.
6805 */
6806 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
6807 baseType->attributeWildcard) == -1)
6808 return (-1);
6809 } else {
6810 /*
6811 * Just inherit the wildcard.
6812 */
6813 type->attributeWildcard = baseType->attributeWildcard;
6814 }
6815 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006816
6817 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6818 if (type->attributeWildcard != NULL) {
6819 /*
6820 * Derivation Valid (Restriction, Complex)
6821 * 4.1 The {base type definition} must also have one.
Daniel Veillard50355f02004-06-08 17:52:16 +00006822 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006823 if (baseType->attributeWildcard == NULL) {
6824 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
6825 "The derived type \"%s\" has an attribute wildcard, "
6826 "but the base type \"%s\" does not have one.\n",
6827 type->name, baseType->name);
6828 return (1);
6829 } else if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6830 type->attributeWildcard, baseType->attributeWildcard) == 0) {
6831 /* 4.2 */
6832 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
6833 "The wildcard in the derived type \"%s\" is not a valid "
6834 "subset of the one in the base type \"%s\".\n",
6835 type->name, baseType->name);
6836 return (1);
6837 }
6838 /* 4.3 Unless the {base type definition} is the ·ur-type
6839 * definition·, the complex type definition's {attribute
6840 * wildcard}'s {process contents} must be identical to or
6841 * stronger than the {base type definition}'s {attribute
6842 * wildcard}'s {process contents}, where strict is stronger
6843 * than lax is stronger than skip.
6844 */
6845 if ((type->baseType != anyType) &&
6846 (type->attributeWildcard->processContents <
6847 baseType->attributeWildcard->processContents)) {
6848 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
6849 "The process contents of the wildcard in the "
6850 "derived type \"%s\" is weaker than "
6851 "that in the base type \"%s\".\n",
6852 type->name, baseType->name);
6853 return (1);
6854 }
Daniel Veillard50355f02004-06-08 17:52:16 +00006855 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006856 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
6857 /*
6858 * Derivation Valid (Extension)
6859 * At this point the type and the base have both, either
6860 * no wildcard or a wildcard.
6861 */
6862 if ((baseType->attributeWildcard != NULL) &&
6863 (baseType->attributeWildcard != type->attributeWildcard)) {
6864 /* 1.3 */
6865 if (xmlSchemaIsWildcardNsConstraintSubset(ctxt,
6866 baseType->attributeWildcard, type->attributeWildcard) == 0) {
6867 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_COS_CT_EXTENDS_1_3,
6868 "The wildcard in the derived type \"%s\" is not a valid "
6869 "superset of the one in the base type \"%s\".\n",
6870 type->name, baseType->name);
6871 return (1);
6872 }
6873 }
6874 }
6875 }
6876 /*
6877 * Removed, since anyType was plugged into the derivation hierarchy.
6878 */
6879 /*
6880 else {
6881 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006882 * Although the complexType is implicitely derived by "restriction"
6883 * from the ur-type, this is not (yet?) reflected by libxml2.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006884 *
Daniel Veillard3646d642004-06-02 19:19:14 +00006885 baseType = NULL;
6886 attrs = type->attributes;
Daniel Veillard50355f02004-06-08 17:52:16 +00006887 if (attrs != NULL) {
6888 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
6889 attrs, &type->attributeWildcard) == -1) {
6890 if ((type->attributeWildcard != NULL) &&
6891 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard))
6892 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6893 return (-1);
6894 }
6895 if ((type->attributeWildcard != NULL) &&
6896 ((type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD) == 0))
6897 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
6898 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006899 } */
Daniel Veillard3646d642004-06-02 19:19:14 +00006900 /*
6901 * Gather attribute uses defined by this type.
6902 */
6903 if (attrs != NULL) {
6904 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
6905 &uses, &lastUse) == -1) {
6906 return (-1);
6907 }
6908 }
6909 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
6910 * "Two distinct attribute declarations in the {attribute uses} must
6911 * not have identical {name}s and {target namespace}s."
6912 *
6913 * For "extension" this is done further down.
6914 */
6915 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
6916 cur = uses;
6917 while (cur != NULL) {
6918 tmp = cur->next;
6919 while (tmp != NULL) {
6920 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6921 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
6922 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
6923 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
6924
6925 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
6926 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
6927 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6928 break;
6929 }
6930 tmp = tmp->next;
6931 }
6932 cur = cur->next;
6933 }
6934 }
6935 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
6936 /*
6937 * Derive by restriction.
6938 */
6939 if (baseIsAnyType) {
6940 type->attributeUses = uses;
6941 } else {
6942 int found;
6943
6944 cur = uses;
6945 while (cur != NULL) {
6946 found = 0;
6947 base = type->attributeUses;
6948 while (base != NULL) {
6949 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
6950 xmlSchemaGetOnymousAttrName(base->attr))) &&
6951 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr),
6952 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) base->attr)))) {
6953
6954 found = 1;
6955 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6956 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6957 /*
6958 * derivation-ok-restriction 2.1.1
6959 */
6960 xmlSchemaPErr(ctxt, cur->attr->node,
6961 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
6962 "derivation-ok-restriction.2.1.1: "
6963 "The \"optional\" attribute "
6964 "use \"%s\" is inconsistent with a matching "
6965 "\"required\" attribute use of the base type\n",
6966 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6967 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
6968 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
6969 /*
6970 * derivation-ok-restriction 3
6971 */
6972 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
6973 "derivation-ok-restriction.3: "
6974 "The \"required\" attribute use \"%s\" of the base type "
6975 "does not have a matching attribute use in the derived type\n",
6976 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
6977
6978 } else {
6979 /*
6980 * Override the attribute use.
6981 */
6982 base->attr = cur->attr;
6983 }
6984 /*
6985 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00006986 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00006987 */
6988 break;
6989 }
6990 base = base->next;
6991 }
6992
6993 if (!found) {
6994 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
6995 /*
6996 * derivation-ok-restriction 2.2
6997 */
6998 if ((type->attributeWildcard != NULL) &&
6999 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
7000 cur->attr->targetNamespace))
7001 found = 1;
7002
7003 if (!found) {
7004 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
7005 "derivation-ok-restriction.2.2: "
7006 "The attribute use \"%s\" has neither a matching attribute use, "
7007 "nor a matching wildcard in the base type\n",
7008 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
7009 } else {
7010 /*
7011 * Add the attribute use.
7012 *
7013 * Note that this may lead to funny derivation error reports, if
7014 * multiple equal attribute uses exist; but this is not
7015 * allowed anyway, and it will be reported beforehand.
7016 */
7017 tmp = cur;
7018 if (prev != NULL)
7019 prev->next = cur->next;
7020 else
7021 uses = cur->next;
7022 cur = cur->next;
7023 if (type->attributeUses == NULL) {
7024 type->attributeUses = tmp;
7025 } else
7026 lastBaseUse->next = tmp;
7027 lastBaseUse = tmp;
7028
7029 continue;
7030 }
7031 }
7032 }
7033 prev = cur;
7034 cur = cur->next;
7035 }
7036 if (uses != NULL)
7037 xmlSchemaFreeAttributeUseList(uses);
7038 }
7039 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
7040 /*
7041 * The spec allows only appending, and not other kinds of extensions.
7042 *
7043 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
7044 */
7045 if (uses != NULL) {
7046 if (type->attributeUses == NULL) {
7047 type->attributeUses = uses;
7048 } else
7049 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00007050 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007051 } else {
7052 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00007053 * Derive implicitely from the ur-type.
7054 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007055 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00007056 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007057 /*
7058 * 3.4.6 -> Complex Type Definition Properties Correct
7059 */
7060 if (type->attributeUses != NULL) {
7061 cur = type->attributeUses;
7062 prev = NULL;
7063 while (cur != NULL) {
7064 /*
7065 * 4. Two distinct attribute declarations in the {attribute uses} must
7066 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00007067 *
Daniel Veillard3646d642004-06-02 19:19:14 +00007068 * Note that this was already done for "restriction" and types derived from
7069 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00007070 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007071 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
7072 tmp = cur->next;
7073 while (tmp != NULL) {
7074 if ((xmlStrEqual(xmlSchemaGetOnymousAttrName(cur->attr),
7075 xmlSchemaGetOnymousAttrName(tmp->attr))) &&
7076 (xmlStrEqual(xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) cur->attr ),
7077 xmlSchemaGetOnymousTargetNsURI((xmlSchemaTypePtr) tmp->attr)))) {
7078
7079 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_4,
7080 "ct-props-correct.4: Duplicate attribute use with the name \"%s\" specified\n",
7081 xmlSchemaGetOnymousAttrName(cur->attr), NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00007082 break;
7083 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007084 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00007085 }
7086 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007087 /*
7088 * 5. Two distinct attribute declarations in the {attribute uses} must
7089 * not have {type definition}s which are or are derived from ID.
7090 */
7091 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00007092 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007093 if (id != NULL) {
7094 xmlSchemaPErr(ctxt, cur->attr->node, XML_SCHEMAP_CT_PROPS_CORRECT_5,
7095 "ct-props-correct.5: Two attribute declarations, "
7096 "\"%s\" and \"%s\" have types which derived from ID\n",
7097 xmlSchemaGetOnymousAttrName(id->attr),
7098 xmlSchemaGetOnymousAttrName(cur->attr));
Daniel Veillard50355f02004-06-08 17:52:16 +00007099 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007100 id = cur;
7101 }
7102 /*
7103 * Remove "prohibited" attribute uses. The reason this is done at this late
7104 * stage is to be able to catch dublicate attribute uses. So we had to keep
7105 * prohibited uses in the list as well.
7106 */
7107 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7108 tmp = cur;
7109 if (prev == NULL)
7110 type->attributeUses = cur->next;
7111 else
7112 prev->next = cur->next;
7113 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00007114 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00007115 } else {
7116 prev = cur;
7117 cur = cur->next;
7118 }
7119 }
7120 }
7121 /*
7122 * TODO: This check should be removed if we are 100% sure of
7123 * the base type attribute uses already being built.
7124 */
7125 if ((baseType != NULL) && (!baseIsAnyType) &&
7126 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
7127 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
7128 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007129 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00007130 "attribute uses not builded on base type \"%s\".\n",
7131 baseType->name, NULL);
7132 }
7133 return (0);
7134}
7135
7136/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00007137 * xmlSchemaTypeFinalContains:
7138 * @schema: the schema
7139 * @type: the type definition
7140 * @final: the final
7141 *
7142 * Evaluates if a type definition contains the given "final".
7143 * This does take "finalDefault" into account as well.
7144 *
7145 * Returns 1 if the type does containt the given "final",
7146 * 0 otherwise.
7147 */
7148static int
7149xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
7150{
7151 int tfinal = final, tflags = type->flags;
7152
7153 if (type == NULL)
7154 return (0);
7155 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
7156 switch (final) {
7157 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
7158 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7159 break;
7160 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
7161 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7162 break;
7163 case XML_SCHEMAS_TYPE_FINAL_LIST:
7164 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
7165 break;
7166 case XML_SCHEMAS_TYPE_FINAL_UNION:
7167 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
7168 break;
7169 }
7170 tflags = schema->flags;
7171 }
7172 if (tflags & tfinal)
7173 return (1);
7174 else
7175 return (0);
7176
7177}
7178
7179/**
7180 * xmlSchemaGetUnionSimpleTypeMemberTypes:
7181 * @type: the Union Simple Type
7182 *
7183 * Returns a list of member types of @type if existing,
7184 * returns NULL otherwise.
7185 */
7186xmlSchemaTypeLinkPtr
7187xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
7188{
7189 while (type != NULL) {
7190 if (type->memberTypes != NULL)
7191 return (type->memberTypes);
7192 else
7193 type = type->baseType;
7194 }
7195 return (NULL);
7196}
7197
7198/**
7199 * xmlSchemaGetListSimpleTypeItemType:
7200 * @type: the simple type definition
7201 *
7202 * Returns the item type definition of the list simple type.
7203 */
7204static xmlSchemaTypePtr
7205xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
7206{
7207 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
7208 return (NULL);
7209 /*
7210 * Note: In libxml2, the built-in types do not reflect
7211 * the datatype hierarchy (yet?) - we have to treat them
7212 * in a special way.
7213 */
7214 if (type->type == XML_SCHEMA_TYPE_BASIC)
7215 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
7216 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
7217 /* 1 If the <list> alternative is chosen, then the type
7218 * definition ·resolved· to by the ·actual value· of the
7219 * itemType [attribute] of <list>, if present, otherwise
7220 * the type definition corresponding to the <simpleType>
7221 * among the [children] of <list>.
7222 */
7223 return (type->subtypes->subtypes);
7224 else {
7225 /* 2 If the <restriction> option is chosen, then the
7226 * {item type definition} of the {base type definition}.
7227 */
7228 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
7229 }
7230}
7231
7232/**
7233 * xmlSchemaCheckCOSSTDerivedOK:
7234 * @type: the derived simple type definition
7235 * @baseType: the base type definition
7236 *
7237 * Checks wheter @type can be validly
7238 * derived from @baseType.
7239 *
7240 * Returns 0 on success, an positive error code otherwise.
7241 */
7242static int
7243xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
7244 xmlSchemaTypePtr type,
7245 xmlSchemaTypePtr baseType,
7246 int subset)
7247{
7248 /*
7249 * Schema Component Constraint: Type Derivation OK (Simple)
7250 *
7251 *
7252 * 1 They are the same type definition.
7253 * TODO: The identy check might have to be more complex than this.
7254 */
7255 if (type == baseType)
7256 return (0);
7257 /*
7258 * 2.1 restriction is not in the subset, or in the {final}
7259 * of its own {base type definition};
7260 */
7261 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
7262 (xmlSchemaTypeFinalContains(schema,
7263 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
7264 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
7265 }
7266 /* 2.2 */
7267 if (type->baseType == baseType) {
7268 /*
7269 * 2.2.1 D's ·base type definition· is B.
7270 */
7271 return (0);
7272 }
7273 /*
7274 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
7275 * and is validly derived from B given the subset, as defined by this
7276 * constraint.
7277 */
7278 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
7279 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
7280 return (0);
7281 }
7282 /*
7283 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
7284 * definition·.
7285 */
7286 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
7287 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
7288 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
7289 return (0);
7290 }
7291 /*
7292 * 2.2.4 B's {variety} is union and D is validly derived from a type
7293 * definition in B's {member type definitions} given the subset, as
7294 * defined by this constraint.
7295 *
7296 * NOTE: This seems not to involve built-in types, since there is no
7297 * built-in Union Simple Type.
7298 */
7299 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7300 xmlSchemaTypeLinkPtr cur;
7301
7302 cur = baseType->memberTypes;
7303 while (cur != NULL) {
7304 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
7305 cur->type, subset) == 0)
7306 return (0);
7307 cur = cur->next;
7308 }
7309 }
7310
7311 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
7312}
7313
7314
7315/**
7316 * xmlSchemaCheckSTPropsCorrect:
7317 * @ctxt: the schema parser context
7318 * @type: the simple type definition
7319 *
7320 * Checks st-props-correct.
7321 *
7322 * Returns 0 if the properties are correct,
7323 * if not, a positive error code and -1 on internal
7324 * errors.
7325 */
7326static int
7327xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
7328 xmlSchemaTypePtr type)
7329{
7330 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
7331 anyType;
7332
7333 /*
7334 * Schema Component Constraint: Simple Type Definition Properties Correct
7335 *
7336 * NOTE: This is somehow redundant, since we actually built a simple type
7337 * to have all the needed information; this acts as an self test.
7338 */
7339 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
7340 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
7341 /*
7342 * TODO: 1 The values of the properties of a simple type definition must be as
7343 * described in the property tableau in Datatype definition, modulo the
7344 * impact of Missing Sub-components (§5.3).
7345 */
7346 /* Base type: If the datatype has been ·derived· by ·restriction·
7347 * then the Simple Type Definition component from which it is ·derived·,
7348 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
7349 */
7350 if (baseType == NULL) {
7351 xmlSchemaPErr(ctxt, type->node,
7352 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7353 "Simple type \"%s\" does not have a base type.\n",
7354 type->name, NULL);
7355 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7356 }
7357 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
7358 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
7359 (baseType == anyType))) {
7360 xmlSchemaPErr(ctxt, type->node,
7361 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7362 "Simple type \"%s\": its base type \"%s\" is not a simple "
7363 "type.\n",
7364 type->name, baseType->name);
7365 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7366 }
7367 if ((baseType != anySimpleType) &&
7368 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
7369 xmlSchemaPErr(ctxt, type->node,
7370 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7371 "Simple type \"%s\" (not derived by restriction) must have"
7372 "the simple ur-type definition as base type, not \"%s\".\n",
7373 type->name, NULL);
7374 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7375 }
7376 /*
7377 * Variety: One of {atomic, list, union}.
7378 */
7379 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7380 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
7381 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7382 xmlSchemaPErr(ctxt, type->node,
7383 XML_SCHEMAP_ST_PROPS_CORRECT_1,
7384 "Simple type \"%s\" has an absent variety.\n",
7385 type->name, NULL);
7386 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
7387 }
7388 /* TODO: Finish this. */
7389
7390 /*
7391 * 2 All simple type definitions must be derived ultimately from the ·simple
7392 * ur-type definition (so· circular definitions are disallowed). That is, it
7393 * must be possible to reach a built-in primitive datatype or the ·simple
7394 * ur-type definition· by repeatedly following the {base type definition}.
7395 */
7396 baseType = type->baseType;
7397 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
7398 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7399 xmlSchemaTypeFixup(baseType, ctxt, NULL);
7400 if (baseType == anySimpleType)
7401 break;
7402 else if (baseType == type) {
7403 xmlSchemaPErr(ctxt, type->node,
7404 XML_SCHEMAP_ST_PROPS_CORRECT_2,
7405 "Simple type \"%s\" is not derived from the simple "
7406 "ur-type definition (circular definitions are disallowed).\n",
7407 type->name, NULL);
7408 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
7409 }
7410 baseType = baseType->baseType;
7411 }
7412 /*
7413 * 3 The {final} of the {base type definition} must not contain restriction.
7414 */
7415 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
7416 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7417 xmlSchemaPErr(ctxt, type->node,
7418 XML_SCHEMAP_ST_PROPS_CORRECT_3,
7419 "Simple type \"%s\": the \"final\" of its base type "
7420 "\"%s\" must not contain \"restriction\".\n",
7421 type->name, baseType->name);
7422 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
7423 }
7424 return (0);
7425}
7426
7427/**
7428 * xmlSchemaCheckDerivationValidSimpleRestriction:
7429 * @ctxt: the schema parser context
7430 * @type: the simple type definition
7431 *
7432 * Checks if the given @type (simpleType) is derived
7433 * validly by restriction.
7434 *
7435 * Returns -1 on internal errors, 0 if the type is validly derived,
7436 * a positive error code otherwise.
7437 */
7438static int
7439xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
7440 xmlSchemaTypePtr type)
7441{
7442
7443 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
7444 xmlSchemaPErr(ctxt, type->node,
7445 XML_ERR_INTERNAL_ERROR,
7446 "xmlSchemaCheckDerivationValidSimpleRestriction: the given "
7447 "type \"%s\" is not a user-derived simpleType.\n",
7448 type->name, NULL);
7449 return (-1);
7450 }
7451
7452 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
7453 xmlSchemaTypePtr primitive;
7454 /*
7455 * 1.1 The {base type definition} must be an atomic simple
7456 * type definition or a built-in primitive datatype.
7457 */
7458 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7459 xmlSchemaPErr(ctxt, type->node,
7460 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
7461 "Atomic simple type \"%s\": "
7462 "its base type \"%s\" is not an atomic simple type.\n",
7463 type->name, NULL);
7464 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
7465 }
7466 /* 1.2 The {final} of the {base type definition} must not contain
7467 * restriction.
7468 */
7469 /* OPTIMIZE: This is already done in xmlSchemaCheckStPropsCorrect */
7470 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7471 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7472 xmlSchemaPErr(ctxt, type->node,
7473 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
7474 "Atomic simple type \"%s\": the \"final\" of its base type "
7475 "\"%s\" must not contain \"restriction\".\n",
7476 type->name, type->baseType->name);
7477 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
7478 }
7479
7480 /*
7481 * 1.3.1 DF must be an allowed constraining facet for the {primitive
7482 * type definition}, as specified in the appropriate subsection of 3.2
7483 * Primitive datatypes.
7484 */
7485 if (type->facets != NULL) {
7486 xmlSchemaFacetPtr facet;
7487 int ok = 1;
7488
7489 primitive = xmlSchemaGetPrimitiveType(type);
7490 if (primitive == NULL) {
7491 xmlSchemaPErr(ctxt, type->node,
7492 XML_ERR_INTERNAL_ERROR,
7493 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
7494 "to get primitive type of type \"%s\".\n",
7495 type->name, NULL);
7496 return (-1);
7497 }
7498 facet = type->facets;
7499 do {
7500 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
7501 xmlSchemaPErrExt(ctxt, type->node,
7502 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
7503 NULL, NULL, NULL,
7504 "Atomic simple type \"%s\": the facet \"%s\" "
7505 "is not allowed on primitive type \"%s\".\n",
7506 type->name,
7507 xmlSchemaFacetTypeToString(facet->type),
7508 primitive->name, NULL, NULL);
7509
7510 ok = 0;
7511 }
7512 facet = facet->next;
7513 } while (facet != NULL);
7514 if (ok == 0)
7515 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
7516
7517 }
7518 /*
7519 * TODO: 1.3.2 (facet derivation)
7520 */
7521 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
7522 xmlSchemaTypePtr itemType = NULL;
7523
7524 itemType = xmlSchemaGetListSimpleTypeItemType(type);
7525 if (itemType == NULL) {
7526 xmlSchemaPErr(ctxt, type->node,
7527 XML_ERR_INTERNAL_ERROR,
7528 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
7529 "failed to evaluate the item type of type \"%s\".\n",
7530 type->name, NULL);
7531 return (-1);
7532 }
7533 /*
7534 * 2.1 The {item type definition} must have a {variety} of atomic or
7535 * union (in which case all the {member type definitions}
7536 * must be atomic).
7537 */
7538 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7539 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
7540 xmlSchemaPErr(ctxt, type->node,
7541 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7542 "List simple type \"%s\": its item type \"%s\" "
7543 "is not an atomic or union simple type.\n",
7544 type->name, itemType->name);
7545 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7546 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7547 xmlSchemaTypeLinkPtr member;
7548
7549 member = itemType->memberTypes;
7550 while (member != NULL) {
7551 if ((member->type->flags &
7552 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
7553 xmlSchemaPErr(ctxt, type->node,
7554 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
7555 "List simple type \"%s\": its item type "
7556 "is a union simple type, but the member type "
7557 "\"%s\" of this item type is not an \"atomic\" "
7558 "simple type.\n",
7559 type->name, member->type->name);
7560 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
7561 }
7562 member = member->next;
7563 }
7564 }
7565
7566 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7567 xmlSchemaFacetPtr facet;
7568 /*
7569 * This is the case if we have: <simpleType><list ..
7570 */
7571 /*
7572 * 2.3.1
7573 * 2.3.1.1 The {final} of the {item type definition} must not
7574 * contain list.
7575 */
7576 if (xmlSchemaTypeFinalContains(ctxt->schema,
7577 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
7578 xmlSchemaPErr(ctxt, type->node,
7579 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
7580 "List simple type \"%s\": the \"final\" of its item type "
7581 "\"%s\" must not contain \"list\".\n",
7582 type->name, itemType->name);
7583 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
7584 }
7585 /*
7586 * 2.3.1.2 The {facets} must only contain the whiteSpace
7587 * facet component.
7588 */
7589 if (type->facets != NULL) {
7590 facet = type->facets;
7591 do {
7592 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
7593 xmlSchemaPErr(ctxt, type->node,
7594 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
7595 "List simple type \"%s\": the facet \"%s\" "
7596 "is not allowed.\n",
7597 type->name, xmlSchemaFacetTypeToString(facet->type));
7598 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
7599 }
7600 facet = facet->next;
7601 } while (facet != NULL);
7602 }
7603 /*
7604 * TODO: Datatypes states:
7605 * A ·list· datatype can be ·derived· from an ·atomic· datatype
7606 * whose ·lexical space· allows space (such as string or anyURI)or
7607 * a ·union· datatype any of whose {member type definitions}'s
7608 * ·lexical space· allows space.
7609 */
7610 } else {
7611 /*
7612 * This is the case if we have: <simpleType><restriction ...
7613 */
7614 /*
7615 * 2.3.2
7616 * 2.3.2.1 The {base type definition} must have a {variety} of list.
7617 */
7618 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
7619 xmlSchemaPErr(ctxt, type->node,
7620 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
7621 "List simple type \"%s\": its base type \"%s\" must "
7622 "have a variety of list.\n",
7623 type->name, type->baseType->name);
7624 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
7625 }
7626 /*
7627 * 2.3.2.2 The {final} of the {base type definition} must not
7628 * contain restriction.
7629 */
7630 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7631 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7632 xmlSchemaPErr(ctxt, type->node,
7633 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
7634 "List simple type \"%s\": its base type \"%s\" must not "
7635 "have a \"final\" containing \"restriction\".\n",
7636 type->name, type->baseType->name);
7637 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
7638 }
7639 /*
7640 * 2.3.2.3 The {item type definition} must be validly derived
7641 * from the {base type definition}'s {item type definition} given
7642 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
7643 */
7644 {
7645 xmlSchemaTypePtr baseItemType;
7646
7647 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
7648 if (baseItemType == NULL) {
7649 xmlSchemaPErr(ctxt, type->node,
7650 XML_ERR_INTERNAL_ERROR,
7651 "xmlSchemaCheckDerivationValidSimpleRestriction: "
7652 "List simple type \"%s\": failed to "
7653 "evaluate the item type of its base type \"%s\".\n",
7654 type->name, type->baseType->name);
7655 return (-1);
7656 }
7657 if ((itemType != baseItemType) &&
7658 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
7659 baseItemType, 0) != 0)) {
7660 xmlSchemaPErrExt(ctxt, type->node,
7661 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, NULL, NULL, NULL,
7662 "List simple type \"%s\": its item type \"%s\" is not "
7663 "validly derived from the item type \"%s\" of the "
7664 "base type \"%s\" as defined in Type Derivation OK "
7665 "(Simple).\n",
7666 type->name, itemType->name, baseItemType->name,
7667 type->baseType->name, NULL);
7668 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
7669 }
7670 }
7671
7672 if (type->facets != NULL) {
7673 xmlSchemaFacetPtr facet;
7674 int ok = 1;
7675 /*
7676 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
7677 * and enumeration facet components are allowed among the {facets}.
7678 */
7679 facet = type->facets;
7680 do {
7681 switch (facet->type) {
7682 case XML_SCHEMA_FACET_LENGTH:
7683 case XML_SCHEMA_FACET_MINLENGTH:
7684 case XML_SCHEMA_FACET_MAXLENGTH:
7685 case XML_SCHEMA_FACET_WHITESPACE:
7686 /*
7687 * TODO: 2.5.1.2 List datatypes
7688 * The value of ·whiteSpace· is fixed to the value collapse.
7689 */
7690 case XML_SCHEMA_FACET_PATTERN:
7691 case XML_SCHEMA_FACET_ENUMERATION:
7692 break;
7693 default: {
7694 xmlSchemaPErr(ctxt, type->node,
7695 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
7696 "List simple type \"%s\": the facet \"%s\" "
7697 "is not allowed.\n",
7698 type->name,
7699 xmlSchemaFacetTypeToString(facet->type));
7700 /*
7701 * We could return, but it's nicer to report all
7702 * invalid facets.
7703 */
7704 ok = 0;
7705 }
7706 }
7707 facet = facet->next;
7708 } while (facet != NULL);
7709 if (ok == 0)
7710 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
7711 /*
7712 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
7713 * is a facet of the same kind in the {facets} of the {base type
7714 * definition} (call this BF),then the DF's {value} must be a valid
7715 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
7716 */
7717 }
7718
7719
7720 }
7721 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7722 /*
7723 * 3.1 The {member type definitions} must all have {variety} of
7724 * atomic or list.
7725 */
7726 xmlSchemaTypeLinkPtr member;
7727
7728 member = type->memberTypes;
7729 while (member != NULL) {
7730 if (((member->type->flags &
7731 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
7732 ((member->type->flags &
7733 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
7734 xmlSchemaPErr(ctxt, type->node,
7735 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
7736 "Union simple type \"%s\": the member type "
7737 "\"%s\" is not an \"atomic\" simple type.\n",
7738 type->name, member->type->name);
7739 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
7740 }
7741 member = member->next;
7742 }
7743 /*
7744 * 3.3.1 If the {base type definition} is the ·simple ur-type
7745 * definition·
7746 */
7747 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
7748 /*
7749 * 3.3.1.1 All of the {member type definitions} must have a
7750 * {final} which does not contain union.
7751 */
7752 member = type->memberTypes;
7753 while (member != NULL) {
7754 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
7755 XML_SCHEMAS_TYPE_FINAL_UNION)) {
7756 xmlSchemaPErr(ctxt, type->node,
7757 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
7758 "Union simple type \"%s\": the \"final\" of member type "
7759 "\"%s\" contains \"union\".\n",
7760 type->name, member->type->name);
7761 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
7762 }
7763 member = member->next;
7764 }
7765 /*
7766 * 3.3.1.2 The {facets} must be empty.
7767 */
7768 if (type->facetSet != NULL) {
7769 xmlSchemaPErr(ctxt, type->node,
7770 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
7771 "Union simple type \"%s\": the facets must be empty.\n",
7772 type->name, NULL);
7773 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
7774 }
7775 } else {
7776 /*
7777 * 3.3.2.1 The {base type definition} must have a {variety} of union.
7778 */
7779 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
7780 xmlSchemaPErr(ctxt, type->node,
7781 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
7782 "Union simple type \"%s\": its base type \"%s\" has not a "
7783 "variety of union.\n",
7784 type->name, type->baseType->name);
7785 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
7786 }
7787 /*
7788 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
7789 */
7790 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
7791 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
7792 xmlSchemaPErr(ctxt, type->node,
7793 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
7794 "Union simple type \"%s\": the \"final\" of its base "
7795 "type \"%s\" must not contain \"restriction\".\n",
7796 type->name, type->baseType->name);
7797 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
7798 }
7799 /*
7800 * 3.3.2.3 The {member type definitions}, in order, must be validly
7801 * derived from the corresponding type definitions in the {base
7802 * type definition}'s {member type definitions} given the empty set,
7803 * as defined in Type Derivation OK (Simple) (§3.14.6).
7804 */
7805 {
7806 xmlSchemaTypeLinkPtr baseMember;
7807
7808 /*
7809 * OPTIMIZE: if the type is restricting, it has no local defined
7810 * member types and inherits the member types of the base type;
7811 * thus a check for equality can be skipped.
7812 */
7813 /*
7814 * TODO: Even worse: I cannot see a scenario where a restricting
7815 * union simple type can have other member types as the member
7816 * types of it's base type. This check seems not necessary with
7817 * respect to the derivation process in libxml2.
7818 */
7819 if (type->memberTypes != NULL) {
7820 member = type->memberTypes;
7821 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
7822 if ((member == NULL) && (baseMember != NULL)) {
7823 xmlSchemaPErr(ctxt, type->node,
7824 XML_SCHEMAS_ERR_INTERNAL,
7825 "Internal error: "
7826 "xmlSchemaCheckDerivationValidSimpleRestriction "
7827 "(3.3.2.3), union simple type \"%s\", unequal number "
7828 "of member types in the base type\n",
7829 type->name, NULL);
7830 }
7831 while (member != NULL) {
7832 if (baseMember == NULL) {
7833 xmlSchemaPErr(ctxt, type->node,
7834 XML_SCHEMAS_ERR_INTERNAL,
7835 "Internal error: "
7836 "xmlSchemaCheckDerivationValidSimpleRestriction "
7837 "(3.3.2.3), union simple type \"%s\", unequal number "
7838 "of member types in the base type\n",
7839 type->name, NULL);
7840 }
7841 if ((member->type != baseMember->type) &&
7842 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
7843 member->type, baseMember->type, 0) != 0)) {
7844 xmlSchemaPErrExt(ctxt, type->node,
7845 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, NULL,
7846 NULL, NULL,
7847 "Union simple type \"%s\": its member type "
7848 "\"%s\" is not validly derived from its "
7849 "corresponding member type \"%s\" of the base "
7850 "type \"%s\" as defined in Type Derivation OK "
7851 "(Simple).\n",
7852 type->name, member->type->name,
7853 baseMember->type->name,
7854 type->baseType->name, NULL);
7855 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
7856 }
7857 member = member->next;
7858 baseMember = baseMember->next;
7859 }
7860 }
7861 }
7862 /*
7863 * 3.3.2.4 Only pattern and enumeration facet components are
7864 * allowed among the {facets}.
7865 */
7866 if (type->facets != NULL) {
7867 xmlSchemaFacetPtr facet;
7868 int ok = 1;
7869
7870 facet = type->facets;
7871 do {
7872 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
7873 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
7874 xmlSchemaPErr(ctxt, type->node,
7875 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
7876 "Union simple type \"%s\": the facet \"%s\" "
7877 "is not allowed.\n",
7878 type->name,
7879 xmlSchemaFacetTypeToString(facet->type));
7880 ok = 0;
7881 }
7882 facet = facet->next;
7883 } while (facet != NULL);
7884 if (ok == 0)
7885 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
7886
7887 }
7888 /*
7889 * TODO: 3.3.2.5 (facet derivation)
7890 */
7891 }
7892 }
7893
7894 return (0);
7895}
7896
7897/**
7898 * xmlSchemaCheckSRCSimpleType:
7899 * @ctxt: the schema parser context
7900 * @type: the simple type definition
7901 *
7902 * Checks crc-simple-type constraints.
7903 *
7904 * Returns 0 if the constraints are satisfied,
7905 * if not a positive error code and -1 on internal
7906 * errors.
7907 */
7908static int
7909xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
7910 xmlSchemaTypePtr type)
7911{
7912 /*
7913 * NOTE: src-simple-type 2-4 are redundant, since the checks
7914 * were are done for the corresponding <restriction>, <list> and <union>
7915 * elements, but W3C wants a <simpleType> error as well, so it gets one.
7916 * Maby this can be skipped in the future, if we get sure it's not needed.
7917 */
7918 if (type->subtypes == NULL) {
7919 xmlSchemaPErr(ctxt, type->node,
7920 XML_SCHEMAS_ERR_INTERNAL,
7921 "Internal error: xmlSchemaCheckSRCSimpleType, "
7922 "no subtype on simple type \"%s\".\n",
7923 type->name, NULL);
7924 return (-1);
7925 }
7926 /*
7927 * src-simple-type.1 The corresponding simple type definition, if any,
7928 * must satisfy the conditions set out in Constraints on Simple Type
7929 * Definition Schema Components (§3.14.6).
7930 */
7931 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
7932 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
7933 /*
7934 * TODO: Removed this, since it got annoying to get an
7935 * extra error report, if anything failed until now.
7936 * Enable this if needed.
7937 */
7938 /*
7939 xmlSchemaPErr(ctxt, type->node,
7940 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7941 "Simple type \"%s\" does not satisfy the constraints "
7942 "on simple type definitions.\n",
7943 type->name, NULL);
7944 */
7945 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
7946 }
7947
7948 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
7949 /*
7950 * src-simple-type.2 If the <restriction> alternative is chosen,
7951 * either it must have a base [attribute] or a <simpleType> among its
7952 * [children], but not both.
7953 */
7954 if (((type->subtypes->base == NULL) &&
7955 ((type->subtypes->subtypes == NULL) ||
7956 (type->subtypes->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
7957 ((type->subtypes->base != NULL) &&
7958 (type->subtypes->subtypes != NULL) &&
7959 (type->subtypes->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
7960 xmlSchemaPErr(ctxt, type->node,
7961 XML_SCHEMAP_SRC_SIMPLE_TYPE_2,
7962 "Simple type \"%s\": "
7963 "The <restriction> alternative is chosen, thus either the "
7964 "\"base\" attribute or the <simpleType> child "
7965 "must be present, but not both.\n",
7966 type->name, NULL);
7967 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_2);
7968 }
7969 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
7970 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
7971 * an itemType [attribute] or a <simpleType> among its [children],
7972 * but not both.
7973 * NOTE: baseType is set to the local simple type definiton,
7974 * if existent, at parse time. This is a hack and not nice.
7975 */
7976 if (((type->subtypes->base == NULL) &&
7977 (type->baseType == NULL)) ||
7978 ((type->subtypes->base != NULL) &&
7979 (type->subtypes->baseType != NULL))) {
7980 xmlSchemaPErr(ctxt, type->node,
7981 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
7982 "Simple type \"%s\": "
7983 "The <list> alternative is chosen, thus either the "
7984 "\"itemType\" attribute or the <simpleType> child "
7985 "must be present, but not both.\n",
7986 type->name, NULL);
7987 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
7988 }
7989
7990
7991 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
7992 xmlSchemaTypeLinkPtr member;
7993 xmlSchemaTypePtr ancestor, anySimpleType;
7994
7995 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
7996
7997 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
7998 * the <union> alternative is chosen, there must not be any entries
7999 * in the memberTypes [attribute] at any depth which resolve to the
8000 * component corresponding to the <simpleType>.
8001 */
8002 member = type->memberTypes;
8003 while (member != NULL) {
8004 ancestor = member->type;
8005 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
8006 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8007 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
8008 if (ancestor == anySimpleType)
8009 break;
8010 else if (ancestor == type) {
8011 xmlSchemaPErr(ctxt, type->node,
8012 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
8013 "Simple type \"%s\" is not derived from the simple "
8014 "ur-type definition (circular definitions are disallowed).\n",
8015 type->name, NULL);
8016 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
8017 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
8018 /*
8019 * TODO: Although a list simple type must not have a union ST
8020 * type as item type, which in turn has a list ST as member
8021 * type, we will assume this here as well, since this check
8022 * was not yet performed.
8023 */
8024
8025 }
8026 ancestor = ancestor->baseType;
8027 }
8028 member = member->next;
8029 }
8030
8031 }
8032
8033 return (0);
8034}
8035
8036/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008037 * xmlSchemaTypeFixup:
8038 * @typeDecl: the schema type definition
8039 * @ctxt: the schema parser context
8040 *
8041 * Fixes the content model of the type.
8042 */
8043static void
8044xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008045 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008046{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008047 xmlSchemaTypePtr ctxtType;
8048
Daniel Veillard82bbbd42003-05-11 20:16:09 +00008049 if (typeDecl == NULL)
8050 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008051 /*
8052 * Do not allow the following types to be typefixed, prior to
8053 * the corresponding simple/complex types.
8054 */
8055 if (ctxt->ctxtType == NULL) {
8056 switch (typeDecl->type) {
8057 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8058 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8059 case XML_SCHEMA_TYPE_UNION:
8060 case XML_SCHEMA_TYPE_RESTRICTION:
8061 case XML_SCHEMA_TYPE_EXTENSION:
8062 return;
8063 }
8064 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008065 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008066 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008067 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008068 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008069 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
8070 if (typeDecl->subtypes != NULL) {
8071 if (typeDecl->subtypes->contentType ==
8072 XML_SCHEMA_CONTENT_UNKNOWN) {
8073 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8074 NULL);
8075 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008076 typeDecl->contentType =
8077 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008079 break;
8080 }
8081 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008082 xmlSchemaTypePtr base = NULL;
8083
8084 ctxt->ctxtType->flags |=
8085 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086 if (typeDecl->subtypes != NULL)
8087 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008088
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008089 if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008090 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008091 xmlSchemaGetType(ctxt->schema, typeDecl->base,
8092 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008093 if (base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008094 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008095 XML_SCHEMAP_SRC_RESOLVE,
8096 "Restriction \"%s\": the QName \"%s\" of the "
8097 "attribute \"base\" does not resolve to a schema "
8098 "component.\n",
8099 name, typeDecl->base);
8100 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +00008101 XML_SCHEMA_CONTENT_UNKNOWN) {
8102 /*
8103 * The base type might be not "type fixed" yet,
8104 * so do it now. */
8105 /*
8106 * TODO: Is a check for circular derivation already
8107 * done?
8108 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008109 xmlSchemaTypeFixup(base, ctxt, NULL);
8110 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008111 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008112 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8113 /*
8114 * ComplexType restriction.
8115 */
8116 /*
8117 * Base type: The type definition ·resolved· to by the ·actual
8118 * value· of the base [attribute]
8119 */
8120 ctxt->ctxtType->baseType = base;
8121 /*
8122 * Content type.
8123 */
8124 if (typeDecl->subtypes == NULL)
8125 /* 1.1.1 */
8126 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8127 else if ((typeDecl->subtypes->subtypes == NULL) &&
8128 ((typeDecl->subtypes->type ==
8129 XML_SCHEMA_TYPE_ALL)
8130 || (typeDecl->subtypes->type ==
8131 XML_SCHEMA_TYPE_SEQUENCE)))
8132 /* 1.1.2 */
8133 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8134 else if ((typeDecl->subtypes->type ==
8135 XML_SCHEMA_TYPE_CHOICE)
8136 && (typeDecl->subtypes->subtypes == NULL))
8137 /* 1.1.3 */
8138 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
8139 else {
8140 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008141 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008142 XML_SCHEMA_CONTENT_ELEMENTS;
8143 }
8144 } else {
8145 /*
8146 * SimpleType restriction.
8147 */
8148 /* Base type:
8149 * The Simple Type Definition component resolved to by
8150 * the actual value of the base [attribute] or the
8151 * <simpleType> [children], whichever is present.
8152 */
8153 if ((base == NULL) && (typeDecl->subtypes != NULL)) {
8154 base = typeDecl->subtypes;
8155 ctxt->ctxtType->baseType = base;
8156 if (base->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8157 xmlSchemaTypeFixup(base, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008158 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00008159 ctxt->ctxtType->baseType = base;
8160
8161 if (((typeDecl->base == NULL) &&
8162 ((typeDecl->subtypes == NULL) ||
8163 (typeDecl->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
8164 ((typeDecl->base != NULL) &&
8165 (typeDecl->subtypes != NULL) &&
8166 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
8167 /*
8168 * src-restriction-base-or-simpleType
8169 * Either the base [attribute] or the simpleType [child] of the
8170 * <restriction> element must be present, but not both.
8171 */
8172 xmlSchemaPErr(ctxt, typeDecl->node,
8173 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8174 "Restriction \"%s\": "
8175 "Either the \"base\" attribute or the <simpleType> child "
8176 "must be present, but not both.\n",
8177 typeDecl->name, NULL);
8178 }
8179 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008180 break;
8181 }
8182 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008183 xmlSchemaTypePtr base = NULL;
8184 xmlSchemaContentType explicitContentType;
8185
8186 /*
8187 * An extension does exist on a complexType only.
8188 */
8189 ctxt->ctxtType->flags |=
8190 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
8191 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008192 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillard2582a332004-04-18 19:49:46 +00008193 xmlSchemaPErr(ctxt, typeDecl->node,
8194 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8195 "Schemas: extension type %s is recursive\n",
8196 name, NULL);
8197 return;
8198 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008199 if (typeDecl->base != NULL) {
8200 base =
8201 xmlSchemaGetType(ctxt->schema, typeDecl->base,
8202 typeDecl->baseNs);
8203 if (base == NULL) {
8204 xmlSchemaPErr(ctxt, typeDecl->node,
8205 XML_SCHEMAP_SRC_RESOLVE,
8206 "Extension \"%s\": the QName \"%s\" of the "
8207 "attribute \"base\" does not resolve to a schema "
8208 "component.\n",
8209 name, typeDecl->base);
8210 } else if (base->contentType ==
8211 XML_SCHEMA_CONTENT_UNKNOWN) {
8212 typeDecl->recurse = 1;
8213 xmlSchemaTypeFixup(base, ctxt, NULL);
8214 typeDecl->recurse = 0;
8215 }
8216 /*
8217 * The type definition ·resolved· to by the ·actual
8218 * value· of the base [attribute]
8219 */
8220 ctxt->ctxtType->baseType = base;
8221 /*
8222 * TODO: This one is still needed for computation of
8223 * the content model by xmlSchemaBuildAContentModel.
8224 * Try to get rid of it.
8225 */
8226 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008227 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008228 if ((typeDecl->subtypes != NULL) &&
8229 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8230 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
8231
8232 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
8233 if (typeDecl->subtypes == NULL)
8234 /* 1.1.1 */
8235 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8236 else if ((typeDecl->subtypes->subtypes == NULL) &&
8237 ((typeDecl->subtypes->type ==
8238 XML_SCHEMA_TYPE_ALL)
8239 || (typeDecl->subtypes->type ==
8240 XML_SCHEMA_TYPE_SEQUENCE)))
8241 /* 1.1.2 */
8242 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8243 else if ((typeDecl->subtypes->type ==
8244 XML_SCHEMA_TYPE_CHOICE)
8245 && (typeDecl->subtypes->subtypes == NULL))
8246 /* 1.1.3 */
8247 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
8248 if (base != NULL) {
8249 /* It will be reported later, if the base is missing. */
8250 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
8251 /* 2.1 */
8252 typeDecl->contentType = base->contentType;
8253 } else if (base->contentType ==
8254 XML_SCHEMA_CONTENT_EMPTY) {
8255 /* 2.2 imbitable ! */
8256 typeDecl->contentType =
8257 XML_SCHEMA_CONTENT_ELEMENTS;
8258 } else {
8259 /* 2.3 imbitable pareil ! */
8260 typeDecl->contentType =
8261 XML_SCHEMA_CONTENT_ELEMENTS;
8262 }
8263 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008264 break;
8265 }
8266 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008267 ctxtType = ctxt->ctxtType;
8268 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008269 if ((typeDecl->subtypes == NULL) ||
8270 ((typeDecl->subtypes->type !=
8271 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
8272 (typeDecl->subtypes->type !=
8273 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
8274 /*
8275 * This case is understood as shorthand for complex
8276 * content restricting the ur-type definition, and
8277 * the details of the mappings should be modified as
8278 * necessary.
8279 */
8280 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8281 typeDecl->flags |=
8282 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
8283 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008284 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008285 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008286 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8287 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008288 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008289 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008290 if ((typeDecl->subtypes != NULL) &&
8291 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008292 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008293 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008294 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008295 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008296 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008297 typeDecl->contentType =
8298 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008299 } else {
8300 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008301 typeDecl->contentType =
8302 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008303 }
8304 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008305 }
8306 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008307 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008308 break;
8309 }
8310 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
8311 if (typeDecl->subtypes == NULL) {
8312 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +00008313 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
8314 typeDecl->contentType =
8315 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008316 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +00008317 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008318 typeDecl->contentType =
8319 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +00008320 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008321 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
8322 NULL);
8323 if (typeDecl->subtypes != NULL)
8324 typeDecl->contentType =
8325 typeDecl->subtypes->contentType;
8326 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008327 /*
8328 * Removed due to implementation of the build of attribute uses.
8329 */
8330 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008331 if (typeDecl->attributes == NULL)
8332 typeDecl->attributes =
8333 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008334 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008335 }
8336 break;
8337 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008338 case XML_SCHEMA_TYPE_SIMPLE:
8339 /*
8340 * Simple Type Definition Schema Component
8341 *
8342 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008343 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008344 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8345 if (typeDecl->subtypes->contentType ==
8346 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008347 ctxt->ctxtType = typeDecl;
8348 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008349 }
8350 /* Fixup base type */
8351 if ((typeDecl->baseType != NULL) &&
8352 (typeDecl->baseType->contentType ==
8353 XML_SCHEMA_CONTENT_UNKNOWN)) {
8354 /* OPTIMIZE: Actually this one will never by hit, since
8355 * the base type is already type-fixed in <restriction>.
8356 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008357 ctxt->ctxtType = typeDecl;
8358 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008359 }
8360 /* Base type:
8361 * 2 If the <list> or <union> alternative is chosen,
8362 * then the ·simple ur-type definition·.
8363 */
8364 if (typeDecl->subtypes->type ==
8365 XML_SCHEMA_TYPE_LIST) {
8366 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8367 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8368 } else if (typeDecl->subtypes->type ==
8369 XML_SCHEMA_TYPE_UNION) {
8370 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8371 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8372 } else if (typeDecl->subtypes->type ==
8373 XML_SCHEMA_TYPE_RESTRICTION) {
8374 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
8375
8376 /*
8377 * Variety
8378 * If the <restriction> alternative is chosen, then the
8379 * {variety} of the {base type definition}.
8380 */
8381 if (typeDecl->baseType != NULL) {
8382 if (typeDecl->baseType->flags &
8383 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
8384 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
8385 else if (typeDecl->baseType->flags &
8386 XML_SCHEMAS_TYPE_VARIETY_LIST)
8387 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8388 else if (typeDecl->baseType->flags &
8389 XML_SCHEMAS_TYPE_VARIETY_UNION)
8390 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8391 /*
8392 * Schema Component Constraint: Simple Type Restriction
8393 * (Facets)
8394 * NOTE: Satisfaction of 1 and 2 arise from the fixup
8395 * applied beforehand.
8396 *
8397 * 3 The {facets} of R are the union of S and the {facets}
8398 * of B, eliminating duplicates. To eliminate duplicates,
8399 * when a facet of the same kind occurs in both S and the
8400 * {facets} of B, the one in the {facets} of B is not
8401 * included, with the exception of enumeration and pattern
8402 * facets, for which multiple occurrences with distinct values
8403 * are allowed.
8404 */
8405 if (typeDecl->baseType->facetSet != NULL) {
8406 last = typeDecl->facetSet;
8407 if (last != NULL)
8408 while (last->next != NULL)
8409 last = last->next;
8410 cur = typeDecl->baseType->facetSet;
8411 for (; cur != NULL; cur = cur->next) {
8412 /*
8413 * Base patterns won't be add here:
8414 * they are ORed in a type and
8415 * ANDed in derived types. This will
8416 * happed at validation level by
8417 * walking the base axis of the type.
8418 */
8419 if (cur->facet->type ==
8420 XML_SCHEMA_FACET_PATTERN)
8421 continue;
8422 facet = NULL;
8423 if ((typeDecl->facetSet != NULL) &&
8424 (cur->facet->type !=
8425 XML_SCHEMA_FACET_PATTERN) &&
8426 (cur->facet->type !=
8427 XML_SCHEMA_FACET_ENUMERATION)) {
8428 facet = typeDecl->facetSet;
8429 do {
8430 if (cur->facet->type ==
8431 facet->facet->type)
8432 break;
8433 facet = facet->next;
8434 } while (facet != NULL);
8435 }
8436 if (facet == NULL) {
8437 facet = (xmlSchemaFacetLinkPtr)
8438 xmlMalloc(sizeof(xmlSchemaFacetLink));
8439 if (facet == NULL) {
8440 xmlSchemaPErrMemory(ctxt,
8441 "fixing simpleType", NULL);
8442 return;
8443 }
8444 facet->facet = cur->facet;
8445 facet->next = NULL;
8446 if (last == NULL)
8447 typeDecl->facetSet = facet;
8448 else
8449 last->next = facet;
8450 last = facet;
8451 }
8452 }
8453 }
8454 }
8455 }
8456 /*
8457 * Check constraints.
8458 */
8459 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008460 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008461 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008462 case XML_SCHEMA_TYPE_SEQUENCE:
8463 case XML_SCHEMA_TYPE_GROUP:
8464 case XML_SCHEMA_TYPE_ALL:
8465 case XML_SCHEMA_TYPE_CHOICE:
8466 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
8467 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008468 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +00008469 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008470 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8471 break;
8472 case XML_SCHEMA_TYPE_UNION:
8473 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
8474 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
8475 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008476 case XML_SCHEMA_TYPE_BASIC:
8477 case XML_SCHEMA_TYPE_ANY:
8478 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008479 case XML_SCHEMA_TYPE_UR:
8480 case XML_SCHEMA_TYPE_ELEMENT:
8481 case XML_SCHEMA_TYPE_ATTRIBUTE:
8482 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +00008483 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008484 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008485 case XML_SCHEMA_FACET_MININCLUSIVE:
8486 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8487 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8488 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8489 case XML_SCHEMA_FACET_TOTALDIGITS:
8490 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8491 case XML_SCHEMA_FACET_PATTERN:
8492 case XML_SCHEMA_FACET_ENUMERATION:
8493 case XML_SCHEMA_FACET_WHITESPACE:
8494 case XML_SCHEMA_FACET_LENGTH:
8495 case XML_SCHEMA_FACET_MAXLENGTH:
8496 case XML_SCHEMA_FACET_MINLENGTH:
8497 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008498 if (typeDecl->subtypes != NULL)
8499 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008500 break;
8501 }
8502 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008503#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008504 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008505 xmlGenericError(xmlGenericErrorContext,
8506 "Type of %s : %s:%d :", name,
8507 typeDecl->node->doc->URL,
8508 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008509 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008510 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008511 }
Daniel Veillard8651f532002-04-17 09:06:27 +00008512 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008513 case XML_SCHEMA_CONTENT_SIMPLE:
8514 xmlGenericError(xmlGenericErrorContext, "simple\n");
8515 break;
8516 case XML_SCHEMA_CONTENT_ELEMENTS:
8517 xmlGenericError(xmlGenericErrorContext, "elements\n");
8518 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008519 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008520 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
8521 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008522 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008523 xmlGenericError(xmlGenericErrorContext, "empty\n");
8524 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008525 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008526 xmlGenericError(xmlGenericErrorContext, "mixed\n");
8527 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008528 /* Removed, since not used. */
8529 /*
Daniel Veillard8651f532002-04-17 09:06:27 +00008530 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008531 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
8532 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008533 */
Daniel Veillard8651f532002-04-17 09:06:27 +00008534 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008535 xmlGenericError(xmlGenericErrorContext, "basic\n");
8536 break;
8537 default:
8538 xmlGenericError(xmlGenericErrorContext,
8539 "not registered !!!\n");
8540 break;
Daniel Veillard8651f532002-04-17 09:06:27 +00008541 }
8542#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008543}
8544
8545/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008546 * xmlSchemaCheckFacet:
8547 * @facet: the facet
8548 * @typeDecl: the schema type definition
8549 * @ctxt: the schema parser context or NULL
8550 * @name: name of the type
8551 *
8552 * Checks the default values types, especially for facets
8553 *
8554 * Returns 0 if okay or -1 in cae of error
8555 */
8556int
8557xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008558 xmlSchemaTypePtr typeDecl,
8559 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008560{
8561 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
8562 int ret = 0;
8563
8564 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008565 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +00008566 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008567 }
8568 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008569 case XML_SCHEMA_FACET_MININCLUSIVE:
8570 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8571 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8572 case XML_SCHEMA_FACET_MAXEXCLUSIVE:{
8573 /*
8574 * Okay we need to validate the value
8575 * at that point.
8576 */
8577 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008578 xmlSchemaTypePtr base;
8579
8580 /*
8581 * TODO: Try to avoid creating a new context.
8582 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008583 vctxt = xmlSchemaNewValidCtxt(NULL);
8584 if (vctxt == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008585 break;
8586 /* xmlSchemaValidateSimpleValue(vctxt, typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008587 facet->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008588 */
8589 /* The value ·must· be in the
8590 * ·value space· of the ·base type·.
8591 */
8592 base = typeDecl->baseType;
8593 if (base == NULL) {
8594 xmlSchemaPErr(ctxt, typeDecl->node,
8595 XML_SCHEMAS_ERR_INTERNAL,
8596 "Internal error: xmlSchemaCheckFacet, "
8597 "the type \"%s\" has no base type.\n",
8598 typeDecl->name, NULL);
8599 return (-1);
8600 }
8601 vctxt->type = base;
8602 xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008603 facet->val = vctxt->value;
8604 vctxt->value = NULL;
8605 if (facet->val == NULL) {
8606 /* error code */
8607 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008608 xmlSchemaPErrExt(ctxt, facet->node,
8609 XML_SCHEMAP_INVALID_FACET,
8610 NULL, NULL, NULL,
8611 "Type \"%s\": the value \"%s\" of the "
8612 "facet \"%s\" is invalid.\n",
8613 name, facet->value,
8614 xmlSchemaFacetTypeToString(facet->type),
8615 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008616 }
8617 ret = -1;
8618 }
8619 xmlSchemaFreeValidCtxt(vctxt);
8620 break;
8621 }
8622 case XML_SCHEMA_FACET_ENUMERATION:{
8623 /*
8624 * Okay we need to validate the value
8625 * at that point.
8626 */
8627 xmlSchemaValidCtxtPtr vctxt;
8628 int tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008629 xmlSchemaTypePtr base;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008630
Daniel Veillard01fa6152004-06-29 17:04:39 +00008631 /* 4.3.5.5 Constraints on enumeration Schema Components
8632 * Schema Component Constraint: enumeration valid restriction
8633 * It is an ·error· if any member of {value} is not in the
8634 * ·value space· of {base type definition}.
8635 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008636 vctxt = xmlSchemaNewValidCtxt(NULL);
8637 if (vctxt == NULL)
8638 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008639 base = typeDecl->baseType;
8640 if (base == NULL) {
8641 xmlSchemaPErr(ctxt, typeDecl->node,
8642 XML_SCHEMAS_ERR_INTERNAL,
8643 "Internal error: xmlSchemaCheckFacet, "
8644 "the type \"%s\" has no base type.\n",
8645 typeDecl->name, NULL);
8646 return (-1);
8647 }
8648 vctxt->type = base;
8649 tmp = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1);
8650 /* tmp = xmlSchemaValidateSimpleValue(vctxt, typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008651 facet->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008652 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008653 if (tmp != 0) {
8654 if (ctxt != NULL) {
8655 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008656 XML_SCHEMAP_INVALID_ENUM,
8657 "Type \"%s\": the value \"%s\" of the "
8658 "facet \"enumeration\" is invalid.\n",
8659 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008660 }
8661 ret = -1;
8662 }
8663 xmlSchemaFreeValidCtxt(vctxt);
8664 break;
8665 }
8666 case XML_SCHEMA_FACET_PATTERN:
8667 facet->regexp = xmlRegexpCompile(facet->value);
8668 if (facet->regexp == NULL) {
8669 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008670 XML_SCHEMAP_REGEXP_INVALID,
8671 "Type \"%s\": the value \"%s\" of the "
8672 "facet \"pattern\" is invalid.\n",
8673 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674 ret = -1;
8675 }
8676 break;
8677 case XML_SCHEMA_FACET_TOTALDIGITS:
8678 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8679 case XML_SCHEMA_FACET_LENGTH:
8680 case XML_SCHEMA_FACET_MAXLENGTH:
8681 case XML_SCHEMA_FACET_MINLENGTH:{
8682 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008683
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008684 tmp =
8685 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
8686 facet->value,
8687 &facet->val);
8688 if (tmp != 0) {
8689 /* error code */
8690 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008691 xmlSchemaPErrExt(ctxt, facet->node,
8692 XML_SCHEMAP_INVALID_FACET_VALUE,
8693 NULL, NULL, NULL,
8694 "Type \"%s\": the value \"%s\" of the "
8695 "facet \"%s\" is invalid.\n",
8696 name, facet->value,
8697 xmlSchemaFacetTypeToString(facet->type),
8698 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008699 }
8700 ret = -1;
8701 }
8702 break;
8703 }
8704 case XML_SCHEMA_FACET_WHITESPACE:{
8705 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
8706 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
8707 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
8708 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
8709 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
8710 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
8711 } else {
8712 if (ctxt != NULL) {
8713 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008714 XML_SCHEMAP_INVALID_WHITE_SPACE,
8715 "Type \"%s\": the value \"%s\" of the "
8716 "facet \"whiteSpace\" is invalid.\n",
8717 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008718 }
8719 ret = -1;
8720 }
8721 }
8722 default:
8723 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008724 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008725 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00008726}
8727
8728/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008729 * xmlSchemaCheckDefaults:
8730 * @typeDecl: the schema type definition
8731 * @ctxt: the schema parser context
8732 *
8733 * Checks the default values types, especially for facets
8734 */
8735static void
8736xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008737 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008738{
Daniel Veillard4255d502002-04-16 15:50:10 +00008739 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008740 name = typeDecl->name;
8741 /*
8742 * NOTE: It is intended to use the facets list, instead
8743 * of facetSet.
8744 */
8745 if (typeDecl->facets != NULL) {
8746 xmlSchemaFacetPtr facet = typeDecl->facets;
8747
8748 while (facet != NULL) {
8749 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
8750 facet = facet->next;
8751 }
8752 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008753}
8754
8755/**
Daniel Veillard13e04c62002-04-23 17:51:29 +00008756 * xmlSchemaAttrGrpFixup:
8757 * @attrgrpDecl: the schema attribute definition
8758 * @ctxt: the schema parser context
8759 * @name: the attribute name
8760 *
8761 * Fixes finish doing the computations on the attributes definitions
8762 */
8763static void
Daniel Veillard3646d642004-06-02 19:19:14 +00008764xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008765 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +00008766{
8767 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00008768 name = attrgrp->name;
8769 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008770 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00008771 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008772 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +00008773
Daniel Veillard3646d642004-06-02 19:19:14 +00008774 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref, attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008775 if (ref == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008776 xmlSchemaPErr(ctxt, attrgrp->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008777 XML_SCHEMAP_SRC_RESOLVE,
8778 "Attribute group \"%s\": the QName \"%s\" of the attribute "
8779 "\"ref\" does not resolve to a schema "
8780 "component.\n",
8781 name, attrgrp->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008782 return;
8783 }
8784 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008785 attrgrp->attributes = ref->attributes;
8786 attrgrp->attributeWildcard = ref->attributeWildcard;
8787 }
8788 /*
8789 * Removed, since a global attribute group does not need to hold any
8790 * attributes or wildcard
8791 */
8792 /*
8793 else {
8794 xmlSchemaPErr(ctxt, attrgrp->node, XML_SCHEMAP_NOATTR_NOREF,
8795 "Schemas: attribute group %s has no attributes nor reference\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008796 name, NULL);
Daniel Veillard13e04c62002-04-23 17:51:29 +00008797 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008798 */
Daniel Veillard13e04c62002-04-23 17:51:29 +00008799}
8800
8801/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008802 * xmlSchemaAttrFixup:
8803 * @attrDecl: the schema attribute definition
8804 * @ctxt: the schema parser context
8805 * @name: the attribute name
8806 *
8807 * Fixes finish doing the computations on the attributes definitions
8808 */
8809static void
8810xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008811 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00008812{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008813 /*
8814 * The simple type definition corresponding to the <simpleType> element
8815 * information item in the [children], if present, otherwise the simple
8816 * type definition ·resolved· to by the ·actual value· of the type
8817 * [attribute], if present, otherwise the ·simple ur-type definition·.
8818 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008819 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008820 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008821 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008822 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008823 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008824 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008825
Daniel Veillard01fa6152004-06-29 17:04:39 +00008826 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
8827 attrDecl->typeNs);
8828 if (type == NULL) {
8829 xmlSchemaPErr(ctxt, attrDecl->node,
8830 XML_SCHEMAP_SRC_RESOLVE,
8831 "Attribute \"%s\": the QName \"%s\" of the attribute "
8832 "\"type\" does not resolve to a schema "
8833 "component.\n",
8834 name, attrDecl->typeName);
8835 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008836 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008837 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008838 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +00008839
Daniel Veillard3646d642004-06-02 19:19:14 +00008840 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008841 if (ref == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008842 xmlSchemaPErr(ctxt, attrDecl->node,
8843 XML_SCHEMAP_SRC_RESOLVE,
8844 "Attribute \"%s\": the QName \"%s\" of the attribute "
8845 "\"ref\" does not resolve to a schema "
8846 "component.\n",
8847 name, attrDecl->ref);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008848 return;
8849 }
8850 xmlSchemaAttrFixup(ref, ctxt, NULL);
8851 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +00008852 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008853 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +00008854 }
8855}
8856
8857/**
8858 * xmlSchemaParse:
8859 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00008860 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00008861 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +00008862 * XML Shema struture which can be used to validate instances.
8863 * *WARNING* this interface is highly subject to change
8864 *
8865 * Returns the internal XML Schema structure built from the resource or
8866 * NULL in case of error
8867 */
8868xmlSchemaPtr
8869xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
8870{
8871 xmlSchemaPtr ret = NULL;
8872 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008873 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008874 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008875 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008876
8877 xmlSchemaInitTypes();
8878
Daniel Veillard6045c902002-10-09 21:13:59 +00008879 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +00008880 return (NULL);
8881
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008882 nberrors = ctxt->nberrors;
8883 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008884 ctxt->counter = 0;
8885 ctxt->container = NULL;
8886
8887 /*
8888 * First step is to parse the input document into an DOM/Infoset
8889 */
Daniel Veillard6045c902002-10-09 21:13:59 +00008890 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008891 doc = xmlReadFile((const char *) ctxt->URL, NULL,
8892 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008893 if (doc == NULL) {
8894 xmlSchemaPErr(ctxt, NULL,
8895 XML_SCHEMAP_FAILED_LOAD,
8896 "xmlSchemaParse: could not load %s\n",
8897 ctxt->URL, NULL);
8898 return (NULL);
8899 }
Daniel Veillard6045c902002-10-09 21:13:59 +00008900 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008901 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
8902 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008903 if (doc == NULL) {
8904 xmlSchemaPErr(ctxt, NULL,
8905 XML_SCHEMAP_FAILED_PARSE,
8906 "xmlSchemaParse: could not parse\n",
8907 NULL, NULL);
8908 return (NULL);
8909 }
8910 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +00008911 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +00008912 } else if (ctxt->doc != NULL) {
8913 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008914 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +00008915 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008916 xmlSchemaPErr(ctxt, NULL,
8917 XML_SCHEMAP_NOTHING_TO_PARSE,
8918 "xmlSchemaParse: could not parse\n",
8919 NULL, NULL);
8920 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008921 }
8922
8923 /*
8924 * Then extract the root and Schema parse it
8925 */
8926 root = xmlDocGetRootElement(doc);
8927 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008928 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8929 XML_SCHEMAP_NOROOT,
8930 "schemas has no root", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +00008931 if (!preserve) {
8932 xmlFreeDoc(doc);
8933 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008934 return (NULL);
8935 }
8936
8937 /*
8938 * Remove all the blank text nodes
8939 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008940 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +00008941
8942 /*
8943 * Then do the parsing for good
8944 */
8945 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +00008946 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +00008947 if (!preserve) {
8948 xmlFreeDoc(doc);
8949 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008950 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +00008951 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008952 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008953 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +00008954
8955 /*
8956 * Then fix all the references.
8957 */
8958 ctxt->schema = ret;
8959 xmlHashScanFull(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008960 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008961
8962 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00008963 * Then fixup all attributes declarations
8964 */
8965 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
8966
8967 /*
8968 * Then fixup all attributes group declarations
8969 */
8970 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
8971 ctxt);
8972
8973 /*
Daniel Veillard4255d502002-04-16 15:50:10 +00008974 * Then fixup all types properties
8975 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008976 ctxt->ctxtType = NULL;
8977 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008978 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
8979
8980 /*
8981 * Then build the content model for all elements
8982 */
8983 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008984 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008985
8986 /*
8987 * Then check the defaults part of the type like facets values
8988 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008989 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
8990 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00008991
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008992 if (ctxt->nberrors != 0) {
8993 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008994 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008996 return (ret);
8997}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008998
Daniel Veillard4255d502002-04-16 15:50:10 +00008999/**
Daniel Veillard01c13b52002-12-10 15:19:08 +00009000 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +00009001 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +00009002 * @err: the error callback
9003 * @warn: the warning callback
9004 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +00009005 *
Daniel Veillard01c13b52002-12-10 15:19:08 +00009006 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00009007 */
9008void
9009xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009010 xmlSchemaValidityErrorFunc err,
9011 xmlSchemaValidityWarningFunc warn, void *ctx)
9012{
Daniel Veillard4255d502002-04-16 15:50:10 +00009013 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009014 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009015 ctxt->error = err;
9016 ctxt->warning = warn;
9017 ctxt->userData = ctx;
9018}
9019
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009020/**
9021 * xmlSchemaFacetTypeToString:
9022 * @type: the facet type
9023 *
9024 * Convert the xmlSchemaTypeType to a char string.
9025 *
9026 * Returns the char string representation of the facet type if the
9027 * type is a facet and an "Internal Error" string otherwise.
9028 */
9029static const char *
9030xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
9031{
9032 switch (type) {
9033 case XML_SCHEMA_FACET_PATTERN:
9034 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009035 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009036 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009037 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009038 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009039 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009040 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009041 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009042 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009043 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009044 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009045 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009046 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009047 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009048 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009049 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009050 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009051 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009052 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009053 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009054 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009055 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009056 return ("fractionDigits");
9057 default:
9058 break;
9059 }
9060 return ("Internal Error");
9061}
9062
9063/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00009064 * xmlSchemaValidateFacetsInternal:
9065 * @ctxt: a schema validation context
9066 * @base: the base type
9067 * @facets: the list of facets to check
9068 * @value: the lexical repr of the value to validate
9069 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +00009070 * @fireErrors: if 0, only internal errors will be fired;
9071 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00009072 *
9073 * Check a value against all facet conditions
9074 *
9075 * Returns 0 if the element is schemas valid, a positive error code
9076 * number otherwise and -1 in case of internal or API error.
9077 */
9078static int
9079xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
9080 xmlSchemaTypePtr base,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009081 xmlSchemaFacetLinkPtr facets,
William M. Bracke7091952004-05-11 15:09:58 +00009082 const xmlChar * value, int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00009083{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009084 int ret = 0;
9085 int tmp = 0;
9086 xmlSchemaTypeType type;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009087 xmlSchemaFacetLinkPtr facetLink = facets;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009088
Daniel Veillard01fa6152004-06-29 17:04:39 +00009089 while (facetLink != NULL) {
9090 type = facetLink->facet->type;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009091 if (type == XML_SCHEMA_FACET_ENUMERATION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009092 tmp = 1;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009093
Daniel Veillard01fa6152004-06-29 17:04:39 +00009094 while (facetLink != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009095 tmp =
Daniel Veillard01fa6152004-06-29 17:04:39 +00009096 xmlSchemaValidateFacet(base, facetLink->facet, value,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009097 ctxt->value);
9098 if (tmp == 0) {
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009099 return 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009100 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009101 facetLink = facetLink->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009102 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009103 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +00009104 tmp = xmlSchemaValidateFacet(base, facetLink->facet, value,
9105 ctxt->value);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009106
9107 if (tmp != 0) {
9108 ret = tmp;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009109 if (fireErrors) {
9110 xmlSchemaVErr(ctxt, ctxt->cur, tmp,
9111 "The value failed to validate against the facet \"%s\".\n",
9112 (const xmlChar *) xmlSchemaFacetTypeToString(type),
9113 NULL);
9114
9115 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009116 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009117 if (facetLink != NULL)
9118 facetLink = facetLink->next;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009119 }
9120 return (ret);
9121}
9122
William M. Brack87640d52004-04-17 14:58:15 +00009123/**
9124 * xmlSchemaValidateFacets:
9125 * @ctxt: a schema validation context
9126 * @base: the base type
9127 * @facets: the list of facets to check
9128 * @value: the lexical repr of the value to validate
9129 * @val: the precomputed value
9130 *
9131 * Check a value against all facet conditions
9132 *
9133 * Returns 0 if the element is schemas valid, a positive error code
9134 * number otherwise and -1 in case of internal or API error.
9135 */
9136static int
9137xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt,
9138 xmlSchemaTypePtr base,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009139 xmlSchemaFacetLinkPtr facets, const xmlChar * value)
William M. Brack87640d52004-04-17 14:58:15 +00009140{
9141 return(xmlSchemaValidateFacetsInternal(ctxt, base, facets, value, 1));
9142}
9143
Daniel Veillard4255d502002-04-16 15:50:10 +00009144/************************************************************************
9145 * *
9146 * Simple type validation *
9147 * *
9148 ************************************************************************/
Daniel Veillard01fa6152004-06-29 17:04:39 +00009149#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +00009150/**
Daniel Veillard377e1a92004-04-16 16:30:05 +00009151 * xmlSchemaValidateSimpleValueUnion:
9152 * @ctxt: a schema validation context
9153 * @type: the type declaration
9154 * @value: the value to validate
9155 *
9156 * Validates a value against a union.
9157 *
9158 * Returns 0 if the value is valid, a positive error code
9159 * number otherwise and -1 in case of internal or API error.
9160 */
9161static int
9162xmlSchemaValidateSimpleValueUnion(xmlSchemaValidCtxtPtr ctxt,
9163 xmlSchemaTypePtr type, const xmlChar * value)
9164{
9165 int ret = 0;
9166 const xmlChar *cur, *end, *prefix, *ncName;
9167 xmlChar *tmp;
9168 xmlSchemaTypePtr subtype;
9169 xmlNsPtr ns;
9170 int len;
9171
9172
9173 /* Process referenced memberTypes. */
9174 cur = type->ref;
9175 do {
9176 while (IS_BLANK_CH(*cur))
9177 cur++;
9178 end = cur;
9179 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9180 end++;
9181 if (end == cur)
9182 break;
9183 tmp = xmlStrndup(cur, end - cur);
9184 ncName = xmlSplitQName3(tmp, &len);
9185 if (ncName != NULL) {
9186 prefix = xmlStrndup(tmp, len);
9187 /* prefix = xmlDictLookup(ctxt->doc->dict, tmp, len); */
9188 } else {
9189 prefix = NULL;
9190 ncName = tmp;
9191 }
William M. Bracke7091952004-05-11 15:09:58 +00009192 /* We won't do additional checks here,
9193 * since they have been performed during parsing. */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009194 ns = xmlSearchNs(type->node->doc, type->node, prefix);
9195 /* namespace = xmlDictLookup(ctxt->doc->dict, ns->href, -1); */
9196 subtype = xmlSchemaGetType(ctxt->schema, ncName, ns->href);
9197 if (tmp != NULL)
9198 xmlFree(tmp);
9199 if (prefix != NULL)
William M. Brack87640d52004-04-17 14:58:15 +00009200 xmlFree((void *)prefix);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009201 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9202 if ((ret == 0) || (ret == -1)) {
9203 return (ret);
9204 }
9205 cur = end;
9206 } while (*cur != 0);
9207
9208 if (type->subtypes != NULL) {
9209 subtype = type->subtypes;
9210 do {
9211 ret = xmlSchemaValidateSimpleValueInternal(ctxt, subtype, value, 0);
9212 if ((ret == 0) || (ret == -1)) {
9213 return (ret);
9214 }
9215 subtype = subtype->next;
9216 } while (subtype != NULL);
9217 }
9218 return (ret);
9219}
9220
9221/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009222 * xmlSchemaValidateSimpleValue:
9223 * @ctxt: a schema validation context
9224 * @type: the type declaration
9225 * @value: the value to validate
9226 *
9227 * Validate a value against a simple type
9228 *
9229 * Returns 0 if the value is valid, a positive error code
9230 * number otherwise and -1 in case of internal or API error.
9231 */
9232static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009233xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009234 xmlSchemaTypePtr type, const xmlChar * value)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009235{
Daniel Veillard377e1a92004-04-16 16:30:05 +00009236 return (xmlSchemaValidateSimpleValueInternal(ctxt, type, value, 1));
9237}
9238
9239/**
9240 * xmlSchemaValidateSimpleValue:
9241 * @ctxt: a schema validation context
9242 * @type: the type declaration
9243 * @value: the value to validate
William M. Bracke7091952004-05-11 15:09:58 +00009244 * @fireErrors: if 0, only internal errors will be fired;
9245 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +00009246 *
9247 * Validate a value against a simple type
9248 *
9249 * Returns 0 if the value is valid, a positive error code
9250 * number otherwise and -1 in case of internal or API error.
9251 */
9252static int
9253xmlSchemaValidateSimpleValueInternal(xmlSchemaValidCtxtPtr ctxt,
William M. Bracke7091952004-05-11 15:09:58 +00009254 xmlSchemaTypePtr type,
9255 const xmlChar * value,
9256 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +00009257{
Daniel Veillard4255d502002-04-16 15:50:10 +00009258 int ret = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009259
Daniel Veillard4255d502002-04-16 15:50:10 +00009260 /*
9261 * First normalize the value accordingly to Schema Datatype
9262 * 4.3.6 whiteSpace definition of the whiteSpace facet of type
William M. Bracke7091952004-05-11 15:09:58 +00009263 *
Daniel Veillard4255d502002-04-16 15:50:10 +00009264 * Then check the normalized value against the lexical space of the
9265 * type.
9266 */
9267 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009268 if (ctxt->value != NULL) {
9269 xmlSchemaFreeValue(ctxt->value);
9270 ctxt->value = NULL;
9271 }
9272 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9273 ctxt->cur);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009274 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009275 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9276 "Failed to validate basic type %s\n",
9277 type->name, NULL);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009278 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009280 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009281
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009282 base = type->baseType;
9283 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009284 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9285 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009286 } else if (type->subtypes != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009287 TODO
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009288 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009289
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009290 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +00009291 * Do not validate facets or attributes when working on
9292 * building the Schemas
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009293 */
9294 if (ctxt->schema != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009295 xmlSchemaFacetLinkPtr facetLink;
9296
9297 if ((ret == 0) && (type->facetSet != NULL)) {
9298 facetLink = type->facetSet;
9299 ret = xmlSchemaValidateFacetsInternal(ctxt, base, facetLink,
William M. Bracke7091952004-05-11 15:09:58 +00009300 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009301 }
9302 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009303 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009304 xmlSchemaTypePtr base;
Daniel Veillard4255d502002-04-16 15:50:10 +00009305
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009306 base = type->subtypes;
9307 if (base != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00009308 ret = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9309 value, fireErrors);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009310 } else {
9311 TODO}
Daniel Veillard4255d502002-04-16 15:50:10 +00009312 } else if (type->type == XML_SCHEMA_TYPE_LIST) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009313 xmlSchemaTypePtr base;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009314 const xmlChar *cur, *end;
9315 xmlChar *tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009316 int ret2;
Daniel Veillard4255d502002-04-16 15:50:10 +00009317
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009318 base = type->subtypes;
9319 if (base == NULL) {
9320 xmlSchemaVErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
9321 "Internal: List type %s has no base type\n",
9322 type->name, NULL);
9323 return (-1);
9324 }
9325 cur = value;
9326 do {
William M. Brack76e95df2003-10-18 16:20:14 +00009327 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009328 cur++;
9329 end = cur;
William M. Brack76e95df2003-10-18 16:20:14 +00009330 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009331 end++;
9332 if (end == cur)
9333 break;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009334 tmp = xmlStrndup(cur, end - cur);
William M. Bracke7091952004-05-11 15:09:58 +00009335 ret2 = xmlSchemaValidateSimpleValueInternal(ctxt, base,
9336 tmp, fireErrors);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009337 xmlFree(tmp);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009338 if (ret2 != 0)
9339 ret = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009340 cur = end;
9341 } while (*cur != 0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009342 } else if (type->type == XML_SCHEMA_TYPE_UNION) {
9343 ret = xmlSchemaValidateSimpleValueUnion(ctxt, type, value);
9344 if ((fireErrors) && (ret != 0)) {
William M. Bracke7091952004-05-11 15:09:58 +00009345 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_VALUE,
9346 "Failed to validate type %s\n", type->name, NULL);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009347 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009348 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009349 TODO
9350 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009351 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009352}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009353#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009354
9355/************************************************************************
9356 * *
9357 * DOM Validation code *
9358 * *
9359 ************************************************************************/
9360
9361static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009362 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009363static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009364 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +00009365 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009366static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009367 xmlNodePtr elem,
9368 xmlSchemaElementPtr elemDecl,
9369 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +00009370
Daniel Veillard3646d642004-06-02 19:19:14 +00009371
9372/**
9373 * xmlSchemaFreeAttrStates:
9374 * @state: a list of attribute states
9375 *
9376 * Free the given list of attribute states
9377 *
9378 */
9379static void
9380xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
9381{
9382 xmlSchemaAttrStatePtr tmp;
9383 while (state != NULL) {
9384 tmp = state;
9385 state = state->next;
9386 xmlFree(tmp);
9387 }
9388}
9389
Daniel Veillard4255d502002-04-16 15:50:10 +00009390/**
9391 * xmlSchemaRegisterAttributes:
9392 * @ctxt: a schema validation context
9393 * @attrs: a list of attributes
9394 *
9395 * Register the list of attributes as the set to be validated on that element
9396 *
9397 * Returns -1 in case of error, 0 otherwise
9398 */
9399static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009400xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
9401{
Daniel Veillard3646d642004-06-02 19:19:14 +00009402 xmlSchemaAttrStatePtr tmp;
9403
9404 ctxt->attr = NULL;
9405 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009406 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009407 if ((attrs->ns != NULL) &&
9408 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
9409 attrs = attrs->next;
9410 continue;
9411 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009412 tmp = (xmlSchemaAttrStatePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00009413 xmlMalloc(sizeof(xmlSchemaAttrState));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009414 if (tmp == NULL) {
9415 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009416 return (-1);
9417 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009418 tmp->attr = attrs;
9419 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
9420 tmp->next = NULL;
9421 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009422 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009423 else
9424 ctxt->attrTop->next = tmp;
9425 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009426 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009427 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009428 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00009429}
9430
9431/**
9432 * xmlSchemaCheckAttributes:
9433 * @ctxt: a schema validation context
9434 * @node: the node carrying it.
9435 *
9436 * Check that the registered set of attributes on the current node
9437 * has been properly validated.
9438 *
9439 * Returns 0 if validity constraints are met, 1 otherwise.
9440 */
9441static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009442xmlSchemaCheckAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9443{
Daniel Veillard4255d502002-04-16 15:50:10 +00009444 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009445 xmlSchemaAttrStatePtr cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00009446
Daniel Veillard3646d642004-06-02 19:19:14 +00009447 cur = ctxt->attr;
9448 while ((cur != NULL) && (cur != ctxt->attrTop->next)) {
9449 if (cur->state != XML_SCHEMAS_ATTR_CHECKED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009450 ret = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009451 if (cur->state == XML_SCHEMAS_ATTR_UNKNOWN)
William M. Bracke7091952004-05-11 15:09:58 +00009452 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009453 "Attribute \"%s\" is not allowed.\n",
9454 cur->attr->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009455 else if (cur->state == XML_SCHEMAS_ATTR_PROHIBITED)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009456 /*
9457 * TODO: This won't ever be touched so remove it.
9458 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009459 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRUNKNOWN,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009460 "Attribute \"%s\" is prohibited.\n",
9461 cur->attr->name, NULL);
9462 else if (cur->state == XML_SCHEMAS_ATTR_INVALID_VALUE) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009463 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ATTRINVALID,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009464 "Attribute \"%s\": the value is not valid.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009465 cur->attr->name, node->name);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009466 } else if (cur->state == XML_SCHEMAS_ATTR_MISSING) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009467 if (cur->decl->ref != NULL)
9468 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009469 "Attribute \"%s\" is required but missing.\n",
9470 cur->decl->ref, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009471 else
9472 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009473 "Attribute \"%s\" is required but missing.\n",
9474 cur->decl->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009475 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009476 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009477 cur = cur->next;
9478 }
9479
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009480 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009481}
9482
William M. Brack29aa7722004-05-12 00:27:56 +00009483#if 0 /* Not currently used - remove if ever needed */
Daniel Veillard4255d502002-04-16 15:50:10 +00009484/**
9485 * xmlSchemaValidateSimpleContent:
9486 * @ctxt: a schema validation context
9487 * @elem: an element
9488 * @type: the type declaration
9489 *
9490 * Validate the content of an element expected to be a simple type
9491 *
9492 * Returns 0 if the element is schemas valid, a positive error code
9493 * number otherwise and -1 in case of internal or API error.
9494 */
9495static int
9496xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009497 xmlNodePtr node ATTRIBUTE_UNUSED)
9498{
Daniel Veillard4255d502002-04-16 15:50:10 +00009499 xmlNodePtr child;
9500 xmlSchemaTypePtr type, base;
9501 xmlChar *value;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +00009502 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009503
9504 child = ctxt->node;
9505 type = ctxt->type;
9506
9507 /*
9508 * Validation Rule: Element Locally Valid (Type): 3.1.3
9509 */
9510 value = xmlNodeGetContent(child);
9511 /* xmlSchemaValidateSimpleValue(ctxt, type, value); */
9512 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009513 case XML_SCHEMA_TYPE_RESTRICTION:{
9514 xmlSchemaFacetPtr facet;
Daniel Veillard4255d502002-04-16 15:50:10 +00009515
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009516 base = type->baseType;
9517 if (base != NULL) {
9518 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9519 } else {
9520 TODO}
9521 if (ret == 0) {
9522 facet = type->facets;
9523 ret =
9524 xmlSchemaValidateFacets(ctxt, base, facet, value);
9525 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009526 /*
9527 * This should attempt to validate the attributes even
9528 * when validation of the value failed.
9529 */
9530 /*
9531 if (type->attributes != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00009532 ret = xmlSchemaValidateAttributes(ctxt, node,
9533 type->attributes);
9534 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009535 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009536 break;
9537 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009538 case XML_SCHEMA_TYPE_EXTENSION:{
9539 TODO
9540 break;
9541 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009542 default:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009543 TODO
9544 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009545 if (value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009546 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +00009547
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009548 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009549}
William M. Brack29aa7722004-05-12 00:27:56 +00009550#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009551
9552/**
9553 * xmlSchemaValidateCheckNodeList
9554 * @nodelist: the list of nodes
9555 *
9556 * Check the node list is only made of text nodes and entities pointing
9557 * to text nodes
9558 *
9559 * Returns 1 if true, 0 if false and -1 in case of error
9560 */
9561static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009562xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
9563{
Daniel Veillard4255d502002-04-16 15:50:10 +00009564 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009565 if (nodelist->type == XML_ENTITY_REF_NODE) {
9566 TODO /* implement recursion in the entity content */
9567 }
9568 if ((nodelist->type != XML_TEXT_NODE) &&
9569 (nodelist->type != XML_COMMENT_NODE) &&
9570 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +00009571 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009572 return (0);
9573 }
9574 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009575 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009576 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009577}
9578
9579/**
9580 * xmlSchemaSkipIgnored:
9581 * @ctxt: a schema validation context
9582 * @type: the current type context
9583 * @node: the top node.
9584 *
9585 * Skip ignorable nodes in that context
9586 *
9587 * Returns the new sibling
9588 * number otherwise and -1 in case of internal or API error.
9589 */
9590static xmlNodePtr
Daniel Veillarddda8f1b2002-09-26 09:47:36 +00009591xmlSchemaSkipIgnored(xmlSchemaValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009592 xmlSchemaTypePtr type, xmlNodePtr node)
9593{
Daniel Veillard4255d502002-04-16 15:50:10 +00009594 /*
9595 * TODO complete and handle entities
9596 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009597 while ((node != NULL) &&
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009598 ((node->type == XML_COMMENT_NODE) ||
Daniel Veillard01fa6152004-06-29 17:04:39 +00009599 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
9600 (node->type == XML_TEXT_NODE)) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009601 (((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
9602 (node->type == XML_TEXT_NODE) && (IS_BLANK_NODE(node)))))) {
9603 node = node->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009604 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009605 return (node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009606}
9607
9608/**
9609 * xmlSchemaValidateCallback:
9610 * @ctxt: a schema validation context
9611 * @name: the name of the element detected (might be NULL)
9612 * @type: the type
9613 *
9614 * A transition has been made in the automata associated to an element
9615 * content model
9616 */
9617static void
9618xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009619 const xmlChar * name ATTRIBUTE_UNUSED,
9620 xmlSchemaTypePtr type, xmlNodePtr node)
9621{
Daniel Veillard4255d502002-04-16 15:50:10 +00009622 xmlSchemaTypePtr oldtype = ctxt->type;
9623 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009624
Daniel Veillard4255d502002-04-16 15:50:10 +00009625#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +00009626 xmlGenericError(xmlGenericErrorContext,
9627 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009628 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009629#endif
9630 ctxt->type = type;
9631 ctxt->node = node;
9632 xmlSchemaValidateContent(ctxt, node);
9633 ctxt->type = oldtype;
9634 ctxt->node = oldnode;
9635}
9636
9637
9638#if 0
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009639
Daniel Veillard4255d502002-04-16 15:50:10 +00009640/**
9641 * xmlSchemaValidateSimpleRestrictionType:
9642 * @ctxt: a schema validation context
9643 * @node: the top node.
9644 *
9645 * Validate the content of a restriction type.
9646 *
9647 * Returns 0 if the element is schemas valid, a positive error code
9648 * number otherwise and -1 in case of internal or API error.
9649 */
9650static int
9651xmlSchemaValidateSimpleRestrictionType(xmlSchemaValidCtxtPtr ctxt,
9652 xmlNodePtr node)
9653{
9654 xmlNodePtr child;
9655 xmlSchemaTypePtr type;
9656 int ret;
9657
9658 child = ctxt->node;
9659 type = ctxt->type;
9660
9661 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009662 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9663 "Internal error: xmlSchemaValidateSimpleRestrictionType %s\n",
9664 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009665 return (-1);
9666 }
9667 /*
9668 * Only text and text based entities references shall be found there
9669 */
9670 ret = xmlSchemaValidateCheckNodeList(child);
9671 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009672 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009673 "Internal error: xmlSchemaValidateSimpleRestrictionType %s content\n",
William M. Bracke7091952004-05-11 15:09:58 +00009674 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009675 return (-1);
9676 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009677 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9678 "Element %s content is not a simple type\n",
9679 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009680 return (-1);
9681 }
9682 ctxt->type = type->subtypes;
9683 xmlSchemaValidateContent(ctxt, node);
9684 ctxt->type = type;
9685 return (ret);
9686}
9687#endif
9688
Daniel Veillard01fa6152004-06-29 17:04:39 +00009689#if 0 /* Not used any more */
Daniel Veillard4255d502002-04-16 15:50:10 +00009690/**
9691 * xmlSchemaValidateSimpleType:
9692 * @ctxt: a schema validation context
9693 * @node: the top node.
9694 *
9695 * Validate the content of an simple type.
9696 *
9697 * Returns 0 if the element is schemas valid, a positive error code
9698 * number otherwise and -1 in case of internal or API error.
9699 */
9700static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009701xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
9702{
Daniel Veillard4255d502002-04-16 15:50:10 +00009703 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +00009704 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +00009705 xmlAttrPtr attr;
9706 int ret;
William M. Bracke7091952004-05-11 15:09:58 +00009707 xmlChar *value;
9708
Daniel Veillard4255d502002-04-16 15:50:10 +00009709
9710 child = ctxt->node;
9711 type = ctxt->type;
9712
9713 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +00009714 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9715 "Internal error: xmlSchemaValidateSimpleType %s\n",
9716 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009717 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009718 }
9719 /*
9720 * Only text and text based entities references shall be found there
9721 */
9722 ret = xmlSchemaValidateCheckNodeList(child);
9723 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009724 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9725 "Internal error: xmlSchemaValidateSimpleType %s content\n",
9726 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009727 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009728 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +00009729 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
9730 "Element %s content is not a simple type\n",
9731 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009732 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009733 }
9734 /*
9735 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +00009736 */
9737
Daniel Veillard4255d502002-04-16 15:50:10 +00009738 attr = node->properties;
9739 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009740 if ((attr->ns == NULL) ||
9741 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
9742 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
9743 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
9744 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
9745 (!xmlStrEqual
9746 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +00009747 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
9748 "Element %s: attribute %s should not be present\n",
9749 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009750 return (ctxt->err);
9751 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009752 }
William M. Bracke7091952004-05-11 15:09:58 +00009753 /* TODO:
9754 * If {variety} is ·atomic· then the {variety} of {base type definition}
9755 * must be ·atomic·.
9756 * If {variety} is ·list· then the {variety} of {item type definition}
9757 * must be either ·atomic· or ·union·.
9758 * If {variety} is ·union· then {member type definitions} must be a list
9759 * of datatype definitions.
9760 */
9761 if (type->subtypes == NULL) {
9762 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9763 "Internal error: xmlSchemaValidateSimpleType; "
9764 "simple type %s does not define a variety\n",
9765 node->name, NULL);
9766 return (ctxt->err);
9767 }
9768 /* Varieties: Restriction or List or Union. */
9769 variety = type->subtypes;
9770 ctxt->type = variety;
9771 value = xmlNodeGetContent(child);
9772 switch (variety->type) {
9773 case XML_SCHEMA_TYPE_RESTRICTION:{
William M. Bracke7091952004-05-11 15:09:58 +00009774 base = variety->baseType;
9775 if (base != NULL) {
9776 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
9777 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009778 TODO}
9779
Daniel Veillard3646d642004-06-02 19:19:14 +00009780 /* Removed due to changes of attribute validation:
William M. Bracke7091952004-05-11 15:09:58 +00009781 if ((ret == 0) && (variety->attributes != NULL)) {
9782 ret = xmlSchemaValidateAttributes(ctxt, node,
9783 variety->attributes);
9784 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009785 */
William M. Bracke7091952004-05-11 15:09:58 +00009786 break;
9787 }
9788 case XML_SCHEMA_TYPE_LIST:
9789 case XML_SCHEMA_TYPE_UNION: {
9790 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
9791 break;
9792 }
9793 default:{
9794 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
9795 "Internal error: xmlSchemaValidateSimpleType; "
9796 "simple type %s defines unknown content: %s\n",
9797 variety->name, NULL);
9798 ret = ctxt->err;
9799 }
9800 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009801 if ((ret == 0) && (variety->facetSet != NULL)) {
9802 ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
9803 }
William M. Bracke7091952004-05-11 15:09:58 +00009804 if (value != NULL)
9805 xmlFree(value);
9806
9807 /* This was removed, since a simple content is not a content of a
9808 * simple type, but of a complex type.
9809 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
9810 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009811 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009812 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00009813}
Daniel Veillard01fa6152004-06-29 17:04:39 +00009814#endif
9815
9816/**
9817 * xmlSchemaValidateSimpleTypeValue:
9818 * @ctxt: a schema validation context
9819 * @value: the value to be validated
9820 * @fireErrors: shall errors be reported?
9821 * @applyFacets: shall facets be applied?
9822 *
9823 * Validates a value by the given type (user derived or built-in).
9824 *
9825 * Returns 0 if the value is valid, a positive error code
9826 * number otherwise and -1 in case of an internal or API error.
9827 * Note on reported errors: Although it might be nice to report
9828 * the name of the simple/complex type, used to validate the content
9829 * of a node, it is quite unnecessary: for global defined types
9830 * the local name of the element is equal to the NCName of the type,
9831 * for local defined types it makes no sense to output the internal
9832 * computed name of the type. TODO: Instead, one should attach the
9833 * struct of the type involved to the error handler - this allows
9834 * the report of any additional information by the user.
9835 * TODO: Correct character normalization of union simple types.
9836 */
9837static int
9838xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
9839 const xmlChar *value,
9840 int fireErrors,
9841 int applyFacets)
9842{
9843 xmlSchemaTypePtr type;
9844 int ret = 0;
9845 type = ctxt->type;
9846
9847 if (type->type == XML_SCHEMA_TYPE_BASIC) {
9848 xmlNodePtr child;
9849
9850 if (ctxt->value != NULL) {
9851 xmlSchemaFreeValue(ctxt->value);
9852 ctxt->value = NULL;
9853 }
9854 child = ctxt->node;
9855 while (child != NULL) {
9856 switch (child->type) {
9857 case XML_TEXT_NODE:
9858 case XML_CDATA_SECTION_NODE:
9859 case XML_PI_NODE:
9860 case XML_COMMENT_NODE:
9861 case XML_XINCLUDE_START:
9862 case XML_XINCLUDE_END:
9863 break;
9864 case XML_ENTITY_REF_NODE:
9865 case XML_ENTITY_NODE:
9866 TODO break;
9867 case XML_ELEMENT_NODE:
9868 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9869 "Element \"%s\": child \"%s\" should not be present.\n",
9870 ctxt->cur->name, child->name);
9871 return (ctxt->err);
9872 case XML_ATTRIBUTE_NODE:
9873 case XML_DOCUMENT_NODE:
9874 case XML_DOCUMENT_TYPE_NODE:
9875 case XML_DOCUMENT_FRAG_NODE:
9876 case XML_NOTATION_NODE:
9877 case XML_HTML_DOCUMENT_NODE:
9878 case XML_DTD_NODE:
9879 case XML_ELEMENT_DECL:
9880 case XML_ATTRIBUTE_DECL:
9881 case XML_ENTITY_DECL:
9882 case XML_NAMESPACE_DECL:
9883#ifdef LIBXML_DOCB_ENABLED
9884 case XML_DOCB_DOCUMENT_NODE:
9885#endif
9886 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
9887 "Element \"%s\": node type of node unexpected here.\n",
9888 ctxt->cur->name, NULL);
9889 return (ctxt->err);
9890 }
9891 child = child->next;
9892 }
9893 ret = xmlSchemaValPredefTypeNode(type, value, &(ctxt->value),
9894 ctxt->cur);
9895 if (ret > 0) {
9896 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
9897 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9898 else
9899 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9900 if (fireErrors) {
9901 if (ctxt->cur->type == XML_ATTRIBUTE_NODE)
9902 xmlSchemaVErr(ctxt, ctxt->cur,
9903 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9904 "The value of attribute \"%s\" is not valid.\n",
9905 ctxt->cur->name, NULL);
9906 else
9907 xmlSchemaVErr(ctxt, ctxt->cur,
9908 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9909 "The value is not valid.\n",
9910 NULL, NULL);
9911 }
9912 } else if (ret < 0) {
9913 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9914 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9915 "validating built-in type \"%s\"\n",
9916 type->name, NULL);
9917 }
9918 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9919 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
9920 * a literal in the ·lexical space· of {base type definition}
9921 */
9922 ctxt->type = type->baseType;
9923 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0);
9924 if (ret < 0) {
9925 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9926 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9927 "validating atomic simple type \"%s\"\n",
9928 type->name, NULL);
9929 } else if (ret > 0) {
9930 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9931 if (fireErrors) {
9932 xmlSchemaVErr(ctxt, ctxt->cur,
9933 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9934 "The value is not valid.\n",
9935 NULL, NULL);
9936 }
9937
9938 } else if ((applyFacets) &&
9939 (type->facetSet != NULL)) {
9940 xmlSchemaTypePtr builtIn;
9941
9942 /*
9943 * Check facets. Be sure to pass the built-in type to
9944 * xmlSchemaValidateFacetsInternal.
9945 */
9946 builtIn = type->baseType;
9947 while (builtIn->type != XML_SCHEMA_TYPE_BASIC)
9948 builtIn = builtIn->baseType;
9949 ret = xmlSchemaValidateFacetsInternal(ctxt, builtIn,
9950 type->facetSet, value, fireErrors);
9951 if (ret < 0) {
9952 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
9953 "Internal error: xmlSchemaValidateSimpleTypeValue, "
9954 "validating facets of atomic simple type \"%s\"\n",
9955 type->name, NULL);
9956 } else if (ret > 0) {
9957 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
9958 if (fireErrors) {
9959 xmlSchemaVErr(ctxt, ctxt->cur,
9960 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
9961 "The value is not valid.\n",
9962 NULL, NULL);
9963 }
9964 }
9965 }
9966 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
9967
9968 xmlSchemaTypePtr tmpType;
9969 const xmlChar *cur, *end;
9970 xmlChar *tmp;
9971 int len = 0;
9972
9973 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
9974 * of white space separated tokens, each of which ·match·es a literal
9975 * in the ·lexical space· of {item type definition}
9976 */
9977
9978 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
9979 cur = value;
9980 do {
9981 while (IS_BLANK_CH(*cur))
9982 cur++;
9983 end = cur;
9984 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9985 end++;
9986 if (end == cur)
9987 break;
9988 tmp = xmlStrndup(cur, end - cur);
9989 len++;
9990 ctxt->type = tmpType;
9991 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1);
9992 xmlFree(tmp);
9993 if (ret > 0) {
9994 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
9995 if (fireErrors) {
9996 xmlSchemaVErr(ctxt, ctxt->cur,
9997 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
9998 "The value is not valid.\n",
9999 NULL, NULL);
10000 }
10001 break;
10002 } else if (ret < 0)
10003 break;
10004 cur = end;
10005 } while (*cur != 0);
10006 /*
10007 * Check facets.
10008 */
10009 if (ret < 0) {
10010 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10011 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10012 "validating list simple type \"%s\"\n",
10013 type->name, NULL);
10014 } else if ((ret == 0) && (applyFacets) &&
10015 (type->facetSet != NULL)) {
10016 int expLen, okFacet = 0, hasFacet = 0;
10017 xmlSchemaFacetPtr facet;
10018 xmlSchemaFacetLinkPtr facetLink;
10019 xmlChar *collapsedValue = NULL;
10020
10021 /*
10022 * The value of ·whiteSpace· is fixed to the value collapse.
10023 */
10024 collapsedValue = xmlSchemaCollapseString((const xmlChar *) value);
10025 if (collapsedValue != NULL)
10026 value = (const xmlChar *) collapsedValue;
10027 facetLink = type->facetSet;
10028 do {
10029 facet = facetLink->facet;
10030 /*
10031 * List types need a special facet treatment.
10032 * Skip whiteSpace, since it is fixed to "collapse".
10033 */
10034 if ((facet->type != XML_SCHEMA_FACET_WHITESPACE) &&
10035 (facet->type != XML_SCHEMA_FACET_PATTERN)) {
10036 ret = xmlSchemaValidateListSimpleTypeFacet(facet, value,
10037 len, &expLen);
10038 if (facet->type == XML_SCHEMA_FACET_ENUMERATION) {
10039 hasFacet = 1;
10040 if (ret == 0)
10041 okFacet = 1;
10042 } else if ((ret > 0) && (fireErrors)) {
10043 char l[25], fl[25];
10044 /* FIXME: What is the max expected string length of the
10045 * length value?
10046 */
10047 snprintf(l, 24, "%d", len);
10048 snprintf(fl, 24, "%d", expLen);
10049 if (ret == XML_SCHEMAV_CVC_LENGTH_VALID) {
10050 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10051 "The value with length \"%s\" is not "
10052 "facet-valid with respect to length = \"%s\".\n",
10053 l, fl);
10054 } else if (ret == XML_SCHEMAV_CVC_MINLENGTH_VALID) {
10055 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10056 "The value with length \"%s\" is not "
10057 "facet-valid with respect to minLength = \"%s\".\n",
10058 l, fl);
10059 } else if (ret == XML_SCHEMAV_CVC_MAXLENGTH_VALID) {
10060 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10061 "The value with length \"%s\" is not "
10062 "facet-valid with respect to maxLength = \"%s\".\n",
10063 l, fl);
10064 } else {
10065 xmlSchemaVErr(ctxt, ctxt->cur, ret,
10066 "The value is not valid with respect "
10067 "to the facet \"%s\".\n",
10068 xmlSchemaFacetTypeToString(facet->type),
10069 NULL);
10070 }
10071 } else if (ret < 0) {
10072 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10073 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10074 "validating facets of list simple type \"%s\"\n",
10075 type->name, NULL);
10076 break;
10077 }
10078 }
10079 facetLink = facetLink->next;
10080 } while (facetLink != NULL);
10081 if (ret >= 0) {
10082 if ((hasFacet) && (okFacet == 0)) {
10083 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
10084 if (fireErrors) {
10085 /*
10086 * TODO: Try to create a report that outputs all the enumeration
10087 * values in use.
10088 */
10089 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
10090 "The value is not valid with respect "
10091 "to the \"enumeration\" facet(s).\n",
10092 NULL, NULL);
10093 }
10094
10095 }
10096 /*
10097 * Pattern facets are ORed at type level and ANDed
10098 * if derived. Walk the base axis.
10099 */
10100 hasFacet = 0;
10101 tmpType = type;
10102 do {
10103 okFacet = 0;
10104 for (facetLink = tmpType->facetSet; facetLink != NULL;
10105 facetLink = facetLink->next) {
10106 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
10107 continue;
10108 okFacet = xmlSchemaValidateListSimpleTypeFacet(
10109 facetLink->facet, value, len, &expLen);
10110 if (okFacet <= 0)
10111 break;
10112 }
10113 if (okFacet != 0)
10114 break;
10115 tmpType = tmpType->baseType;
10116 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
10117 if (okFacet < 0) {
10118 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10119 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10120 "validating \"pattern\" facets of type \"%s\"\n",
10121 type->name, NULL);
10122 } else if (okFacet > 0) {
10123 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
10124 if (fireErrors) {
10125 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_CVC_ENUMERATION_VALID,
10126 "The value is not valid with respect "
10127 "to the \"pattern\" facet(s) of type "
10128 "\"%s\".\n",
10129 tmpType->name, NULL);
10130 }
10131 }
10132 }
10133
10134 if (collapsedValue != NULL)
10135 xmlFree(collapsedValue);
10136 }
10137 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10138 xmlSchemaTypeLinkPtr memberLink;
10139
10140 /*
10141 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
10142 * not apply directly; however, the normalization behavior of ·union·
10143 * types is controlled by the value of whiteSpace on that one of the
10144 * ·memberTypes· against which the ·union· is successfully validated.
10145 *
10146 * This means that the value is normalized by the first validating
10147 * member type, then the facets of the union type are applied. This
10148 * needs changing of the value!
10149 */
10150
10151 /*
10152 * 1.2.3 if {variety} is ·union· then the string must ·match· a
10153 * literal in the ·lexical space· of at least one member of
10154 * {member type definitions}
10155 */
10156 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
10157 if (memberLink == NULL) {
10158 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10159 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10160 "union simple type \"%s\" has no member types\n",
10161 type->name, NULL);
10162 ret = -1;
10163 }
10164 if (ret == 0) {
10165 while (memberLink != NULL) {
10166 ctxt->type = memberLink->type;
10167 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
10168 if ((ret <= 0) || (ret == 0))
10169 break;
10170 memberLink = memberLink->next;
10171 }
10172 if (ret > 0) {
10173 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
10174 if (fireErrors) {
10175 xmlSchemaVErr(ctxt, ctxt->cur,
10176 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3,
10177 "The value is not valid.\n",
10178 NULL, NULL);
10179 }
10180 } else if (ret < 0) {
10181 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10182 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10183 "validating members of union simple type \"%s\"\n",
10184 type->name, NULL);
10185 }
10186 }
10187 /*
10188 * Apply facets (pattern, enumeration).
10189 */
10190 if ((ret == 0) && (applyFacets) &&
10191 (type->facetSet != NULL)) {
10192 xmlSchemaTypePtr anySimpleType;
10193 /*
10194 * Check facets. Be sure to pass the built-in type (the
10195 * simple ur-type in this case) to xmlSchemaValidateFacetsInternal.
10196 */
10197 anySimpleType = type->baseType;
10198 while (anySimpleType->type != XML_SCHEMA_TYPE_BASIC)
10199 anySimpleType = anySimpleType->baseType;
10200 ret = xmlSchemaValidateFacetsInternal(ctxt, anySimpleType,
10201 type->facetSet, value, fireErrors);
10202 if (ret < 0) {
10203 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10204 "Internal error: xmlSchemaValidateSimpleTypeValue, "
10205 "validating facets of union simple type \"%s\"\n",
10206 type->name, NULL);
10207 } else if (ret > 0) {
10208 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
10209 if (fireErrors) {
10210 xmlSchemaVErr(ctxt, ctxt->cur,
10211 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
10212 "The value is not valid.\n",
10213 NULL, NULL);
10214 }
10215 }
10216 }
10217 }
10218 ctxt->type = type;
10219 return (ret);
10220}
10221
10222/**
10223 * xmlSchemaValidateSimpleTypeElement:
10224 * @ctxt: a schema validation context
10225 * @node: the element node to be validated.
10226 *
10227 * Validate the element against a simple type.
10228 *
10229 * Returns 0 if the element is valid, a positive error code
10230 * number otherwise and -1 in case of an internal or API error.
10231 */
10232static int
10233xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10234{
10235 xmlNodePtr child;
10236 xmlSchemaTypePtr type;
10237 xmlAttrPtr attr;
10238 int ret;
10239 xmlChar *value;
10240
10241
10242 child = ctxt->node;
10243 type = ctxt->type;
10244
10245 if ((ctxt == NULL) || (type == NULL)) {
10246 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10247 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
10248 node->name, NULL);
10249 return (-1);
10250 }
10251
10252 /*
10253 * Only text and text based entities references shall be found there
10254 */
10255 ret = xmlSchemaValidateCheckNodeList(child);
10256 if (ret < 0) {
10257 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10258 "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
10259 node->name, NULL);
10260 return (-1);
10261 } else if (ret == 0) {
10262 /* 3.1.2 The element information item must have no element
10263 * information item [children].
10264 */
10265 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
10266 "Element \"%s\" must have no element children.\n",
10267 node->name, NULL);
10268 return (-1);
10269 }
10270 /*
10271 * Validation Rule: Element Locally Valid (Type): 3.1.1
10272 */
10273 attr = node->properties;
10274 while (attr != NULL) {
10275 if ((attr->ns == NULL) ||
10276 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
10277 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
10278 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
10279 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
10280 (!xmlStrEqual
10281 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
10282 xmlSchemaVErr(ctxt, node,
10283 XML_SCHEMAV_CVC_TYPE_3_1_1,
10284 "The attributes of element \"%s\" must be empty, excepting "
10285 "those whose namespace name is identical to "
10286 "http://www.w3.org/2001/XMLSchema-instance and whose local "
10287 "name is one of type, nil, schemaLocation or "
10288 "noNamespaceSchemaLocation.\n",
10289 node->name, attr->name);
10290 return (ctxt->err);
10291 }
10292 attr = attr->next;
10293 }
10294 value = xmlNodeGetContent(child);
10295 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10296 if (value != NULL)
10297 xmlFree(value);
10298
10299 ctxt->type = type;
10300 return (ret);
10301}
Daniel Veillard4255d502002-04-16 15:50:10 +000010302
10303/**
10304 * xmlSchemaValidateElementType:
10305 * @ctxt: a schema validation context
10306 * @node: the top node.
10307 *
10308 * Validate the content of an element type.
10309 * Validation Rule: Element Locally Valid (Complex Type)
10310 *
10311 * Returns 0 if the element is schemas valid, a positive error code
10312 * number otherwise and -1 in case of internal or API error.
10313 */
10314static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010315xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10316{
Daniel Veillard4255d502002-04-16 15:50:10 +000010317 xmlNodePtr child;
10318 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010319 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000010320 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000010321 int ret;
10322 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
10323
Daniel Veillard01fa6152004-06-29 17:04:39 +000010324 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000010325 /*
10326 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
10327 * go in here as well.
10328 */
10329
10330 /* TODO: Is this one called always with an element declaration as the
10331 * context's type?
10332 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010333
10334 oldregexp = ctxt->regexp;
10335
10336 child = ctxt->node;
10337 type = ctxt->type;
10338
10339 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010340 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10341 "Internal error: xmlSchemaValidateElementType\n",
10342 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010343 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010344 }
10345 if (child == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010346 if (type->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010347 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
10348 "Element %s: missing child %s\n",
10349 node->name, type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010350 }
10351 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010352 }
10353
10354 /*
10355 * Verify the element matches
10356 */
10357 if (!xmlStrEqual(child->name, type->name)) {
William M. Bracke7091952004-05-11 15:09:58 +000010358 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
10359 "Element %s: missing child %s found %s\n",
10360 node->name, type->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010361 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010362 }
10363 /*
10364 * Verify the attributes
10365 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010366
10367 attrs = ctxt->attr;
10368 attrTop = ctxt->attrTop;
10369
Daniel Veillard01fa6152004-06-29 17:04:39 +000010370 xmlSchemaRegisterAttributes(ctxt, child->properties);
Daniel Veillard3646d642004-06-02 19:19:14 +000010371
Daniel Veillard4255d502002-04-16 15:50:10 +000010372 /*
10373 * Verify the element content recursively
10374 */
10375 decl = (xmlSchemaElementPtr) type;
10376 oldregexp = ctxt->regexp;
10377 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010378 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
10379 (xmlRegExecCallbacks)
10380 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010381#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010382 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010383#endif
10384 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010385 xmlSchemaValidateType(ctxt, child, (xmlSchemaElementPtr) type,
10386 type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000010387
10388 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010389 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010390#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010391 xmlGenericError(xmlGenericErrorContext,
10392 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010393#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010394 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010395 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10396 "Element %s content check failed\n",
10397 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010398 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010399 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_ELEMCONT,
10400 "Element %s content check failure\n",
10401 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010402#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010403 } else {
10404 xmlGenericError(xmlGenericErrorContext,
10405 "Element %s content check succeeded\n",
10406 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010407
10408#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010409 }
10410 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000010411 }
10412 /*
10413 * Verify that all attributes were Schemas-validated
10414 */
10415 xmlSchemaCheckAttributes(ctxt, node);
Daniel Veillard3646d642004-06-02 19:19:14 +000010416 if (ctxt->attr != NULL)
10417 xmlSchemaFreeAttributeStates(ctxt->attr);
10418 ctxt->attr = attrs;
10419 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000010420 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000010421 ctxt->node = child;
10422 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010423 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010424}
10425
Daniel Veillard01fa6152004-06-29 17:04:39 +000010426#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010427/**
10428 * xmlSchemaValidateBasicType:
10429 * @ctxt: a schema validation context
10430 * @node: the top node.
10431 *
10432 * Validate the content of an element expected to be a basic type type
10433 *
10434 * Returns 0 if the element is schemas valid, a positive error code
10435 * number otherwise and -1 in case of internal or API error.
10436 */
10437static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010438xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10439{
Daniel Veillard4255d502002-04-16 15:50:10 +000010440 int ret;
10441 xmlNodePtr child, cur;
10442 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010443 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +000010444
10445 child = ctxt->node;
10446 type = ctxt->type;
10447
10448 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010449 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10450 "Internal error: xmlSchemaValidateBasicType\n",
10451 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010452 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010453 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010454 if (type->type != XML_SCHEMA_TYPE_BASIC) {
10455 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10456 "Internal error: xmlSchemaValidateBasicType, "
10457 "the given type is not a built-in type.\n",
10458 node->name, NULL);
10459 return (-1);
10460 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010461 /*
10462 * First check the content model of the node.
10463 */
10464 cur = child;
10465 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010466 switch (cur->type) {
10467 case XML_TEXT_NODE:
10468 case XML_CDATA_SECTION_NODE:
10469 case XML_PI_NODE:
10470 case XML_COMMENT_NODE:
10471 case XML_XINCLUDE_START:
10472 case XML_XINCLUDE_END:
10473 break;
10474 case XML_ENTITY_REF_NODE:
10475 case XML_ENTITY_NODE:
10476 TODO break;
10477 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +000010478 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10479 "Element %s: child %s should not be present\n",
10480 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010481 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010482 case XML_ATTRIBUTE_NODE:
10483 case XML_DOCUMENT_NODE:
10484 case XML_DOCUMENT_TYPE_NODE:
10485 case XML_DOCUMENT_FRAG_NODE:
10486 case XML_NOTATION_NODE:
10487 case XML_HTML_DOCUMENT_NODE:
10488 case XML_DTD_NODE:
10489 case XML_ELEMENT_DECL:
10490 case XML_ATTRIBUTE_DECL:
10491 case XML_ENTITY_DECL:
10492 case XML_NAMESPACE_DECL:
10493#ifdef LIBXML_DOCB_ENABLED
10494 case XML_DOCB_DOCUMENT_NODE:
10495#endif
William M. Bracke7091952004-05-11 15:09:58 +000010496 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
10497 "Element %s: node type of node unexpected here\n",
10498 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010499 return (ctxt->err);
10500 }
10501 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010502 }
10503 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010504 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010505 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010506 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +000010507
10508 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010509 xmlSchemaFreeValue(ctxt->value);
10510 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010511 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010512
Daniel Veillard4255d502002-04-16 15:50:10 +000010513 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010514
Daniel Veillard4255d502002-04-16 15:50:10 +000010515 if (value != NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010516 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +000010517 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +000010518 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
10519 "Element %s: failed to validate basic type %s\n",
10520 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010521 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010522 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000010523}
Daniel Veillard01fa6152004-06-29 17:04:39 +000010524#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010525
10526/**
10527 * xmlSchemaValidateComplexType:
10528 * @ctxt: a schema validation context
10529 * @node: the top node.
10530 *
10531 * Validate the content of an element expected to be a complex type type
10532 * xmlschema-1.html#cvc-complex-type
10533 * Validation Rule: Element Locally Valid (Complex Type)
10534 *
10535 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000010536 * number otherwise and -1 in case of internal or API error.
10537 * Note on reported errors: Although it might be nice to report
10538 * the name of the simple/complex type, used to validate the content
10539 * of a node, it is quite unnecessary: for global defined types
10540 * the local name of the element is equal to the NCName of the type,
10541 * for local defined types it makes no sense to output the internal
10542 * computed name of the type. TODO: Instead, one should attach the
10543 * struct of the type involved to the error handler - this allows
10544 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000010545 */
10546static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010547xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10548{
Daniel Veillard4255d502002-04-16 15:50:10 +000010549 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010550 xmlSchemaTypePtr type;
10551 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010552
Daniel Veillard4255d502002-04-16 15:50:10 +000010553 child = ctxt->node;
10554 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010555 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010556
Daniel Veillard4255d502002-04-16 15:50:10 +000010557 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010558 case XML_SCHEMA_CONTENT_EMPTY: {
10559 /*
10560 * 1 If the {content type} is empty, then the element information
10561 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000010562 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010563 /* TODO: Hmm, Xerces reports nodes like Comment to be invalid
10564 * content, but XSV does not.
10565 */
10566 /*
10567 * TODO: Is the entity stuff correct?
10568 */
10569 while (child != NULL) {
10570 if ((child->type == XML_ELEMENT_NODE) ||
10571 /*
10572 * TODO: Ask Daniel if this are all character nodes.
10573 */
10574 (child->type == XML_TEXT_NODE) ||
10575 (child->type == XML_CDATA_SECTION_NODE) ||
10576 (child->type == XML_ENTITY_REF_NODE) ||
10577 (child->type == XML_ENTITY_NODE)) {
10578 break;
10579 }
10580 child = child->next;
10581 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010582 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010583 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
10584 "Character or element children are not allowed, "
10585 "because the content type is empty.\n",
10586 NULL, NULL);
10587 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010588 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010589 }
10590 case XML_SCHEMA_CONTENT_ELEMENTS:
10591 case XML_SCHEMA_CONTENT_MIXED:
10592 while (child != NULL) {
10593 if (child->type == XML_ELEMENT_NODE) {
10594 ret = xmlRegExecPushString(ctxt->regexp,
10595 child->name, child);
10596#ifdef DEBUG_AUTOMATA
10597 if (ret < 0)
10598 xmlGenericError(xmlGenericErrorContext,
10599 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000010600 else
10601 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010602 " --> %s\n", child->name);
10603#endif
10604 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
10605 /*
10606 * TODO: Ask Daniel if this are all character nodes.
10607 */
10608 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
10609 (child->type == XML_ENTITY_NODE) ||
10610 (child->type == XML_ENTITY_REF_NODE) ||
10611 (child->type == XML_CDATA_SECTION_NODE))) {
10612 /*
10613 * 2.3 If the {content type} is element-only, then the
10614 * element information item has no character information
10615 * item [children] other than those whose [character
10616 * code] is defined as a white space in [XML 1.0 (Second
10617 * Edition)].
10618 */
10619 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
10620 "Character children are not allowed, "
10621 "because the content type is element-only.\n",
10622 NULL, NULL);
10623 break;
10624 }
10625 child = child->next;
10626 }
10627 break;
10628 case XML_SCHEMA_CONTENT_SIMPLE:
10629 case XML_SCHEMA_CONTENT_BASIC:{
10630 xmlSchemaTypePtr base, anyType;
10631 xmlChar *value = NULL;
10632 /*
10633 * We hit a complexType with a simpleContent resolving
10634 * to a user derived or built-in simple type.
10635 */
10636 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10637 /*
10638 * Internal check for integrity of the base type.
10639 */
10640 base = type->baseType;
10641 while ((base != NULL) &&
10642 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
10643 (base->type != XML_SCHEMA_TYPE_BASIC) &&
10644 (base != anyType)) {
10645 base = base->baseType;
10646 }
10647 if ((base == NULL) ||
10648 (((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) &&
10649 (base->type != XML_SCHEMA_TYPE_SIMPLE)) ||
10650 ((type->contentType == XML_SCHEMA_CONTENT_BASIC) &&
10651 (base->type != XML_SCHEMA_TYPE_BASIC)))) {
10652 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10653 "Internal error: xmlSchemaValidateComplexType, "
10654 "Element \"%s\": the base type of the corresponding "
10655 "complex type \"%s\" is not a user derived or a "
10656 "built-in simple type.\n",
10657 node->name, type->name);
10658 return (-1);
10659 }
10660 /*
10661 * 2.2 If the {content type} is a simple type definition,
10662 * then the element information item has no element
10663 * information item [children], and the ·normalized value·
10664 * of the element information item is ·valid· with respect
10665 * to that simple type definition as defined by String
10666 * Valid (§3.14.4).
10667 */
10668 child = node->children;
10669 while (child != NULL) {
10670 if (child->type == XML_ELEMENT_NODE) {
10671 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10672 "Element children are not allowed, because "
10673 "the content type is a simple type.\n",
10674 NULL, NULL);
10675 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10676 break;
10677 }
10678 child = child->next;
10679 }
10680 if (ret == 0) {
10681 /*
10682 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000010683 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010684 if (ctxt->node == NULL)
10685 value = NULL;
10686 else
10687 value = xmlNodeGetContent(node);
10688 ctxt->type = base;
10689 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
10690 ctxt->type = type;
10691 if (ret > 0) {
10692 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10693 "The character value "
10694 "is not valid with respect to the simple type.\n",
10695 NULL, NULL);
10696 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10697 } else if (ret < 0) {
10698 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10699 "Internal error: xmlSchemaValidateComplexType, "
10700 "Element \"%s\": error while validating character "
10701 "content against complex type \"%s\".\n",
10702 node->name, type->name);
10703 return (-1);
10704 }
10705 }
10706 if (ret == 0) {
10707 /*
10708 * Apply facets of the complexType. Be sure to pass the
10709 * built-in type to xmlSchemaValidateFacetsInternal.
10710 */
10711 /* TODO: I don't know yet if the facets of the simple type
10712 * are used, or if the facets, defined by this complex type,
10713 * are to be used only. This here applies both facet sets.
10714 */
10715 while (base->type != XML_SCHEMA_TYPE_BASIC)
10716 base = base->baseType;
10717 if (base == NULL) {
10718 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10719 "Internal error: xmlSchemaValidateComplexType, "
10720 "Element \"%s\": error while validating character "
10721 "content against complex type \"%s\"; failed to "
10722 "compute the built-in simple type for facet "
10723 "validation.\n",
10724 node->name, type->name);
10725 return (-1);
10726 }
10727 ret = xmlSchemaValidateFacetsInternal(ctxt, base,
10728 type->facetSet, value, 1);
10729 if (ret > 0) {
10730 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
10731 "The character value "
10732 "is not valid with respect to the simple type.\n",
10733 NULL, NULL);
10734 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
10735 } else if (ret < 0) {
10736 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
10737 "Internal error: xmlSchemaValidateComplexType, "
10738 "Element \"%s\": error while validating character "
10739 "content against complex type \"%s\"; failed to "
10740 "apply facets.\n",
10741 type->name, NULL);
10742 }
10743 }
10744 if (value != NULL)
10745 xmlFree(value);
10746 /* TODO: facets */
10747 break;
10748 }
10749 /*
10750 case XML_SCHEMA_CONTENT_SIMPLE:{
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010751 if (type->subtypes != NULL) {
10752 ctxt->type = type->subtypes;
10753 xmlSchemaValidateComplexType(ctxt, node);
10754 }
10755 if (type->baseType != NULL) {
10756 ctxt->type = type->baseType;
10757 xmlSchemaValidateComplexType(ctxt, node);
10758 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010759 * Removed due to changes of attribute validation:
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010760 if (type->attributes != NULL) {
10761 xmlSchemaValidateAttributes(ctxt, node,
10762 type->attributes);
10763 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010764 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010765 ctxt->type = type;
10766 break;
10767 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010768 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010769 default:
10770 TODO xmlGenericError(xmlGenericErrorContext,
10771 "unimplemented content type %d\n",
10772 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000010773 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010774 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010775 xmlSchemaValidateAttributes(ctxt, node, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010776 }
10777 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010778 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010779}
10780
10781/**
10782 * xmlSchemaValidateContent:
10783 * @ctxt: a schema validation context
10784 * @elem: an element
10785 * @type: the type declaration
10786 *
10787 * Validate the content of an element against the type.
10788 *
10789 * Returns 0 if the element is schemas valid, a positive error code
10790 * number otherwise and -1 in case of internal or API error.
10791 */
10792static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010793xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
10794{
Daniel Veillard4255d502002-04-16 15:50:10 +000010795 xmlNodePtr child;
10796 xmlSchemaTypePtr type;
10797
10798 child = ctxt->node;
10799 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010800 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000010801
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010802 ctxt->cur = node;
Daniel Veillarde19fc232002-04-22 16:01:24 +000010803
Daniel Veillard4255d502002-04-16 15:50:10 +000010804 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010805 case XML_SCHEMA_TYPE_ANY:
10806 /* Any type will do it, fine */
10807 TODO /* handle recursivity */
10808 break;
10809 case XML_SCHEMA_TYPE_COMPLEX:
10810 xmlSchemaValidateComplexType(ctxt, node);
10811 break;
10812 case XML_SCHEMA_TYPE_ELEMENT:{
10813 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
10814
10815 /*
10816 * Handle element reference here
10817 */
10818 if (decl->ref != NULL) {
10819 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010820 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
10821 "Internal error: element reference %s "
10822 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010823 return (-1);
10824 }
10825 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
10826 decl = decl->refDecl;
10827 }
William M. Bracke7091952004-05-11 15:09:58 +000010828 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010829 xmlSchemaValidateElementType(ctxt, node);
10830 ctxt->type = type;
10831 break;
10832 }
10833 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010834 case XML_SCHEMA_TYPE_SIMPLE:
10835 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010836 break;
10837 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010838 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010839 case XML_SCHEMA_TYPE_SEQUENCE:
10840 TODO break;
10841 case XML_SCHEMA_TYPE_CHOICE:
10842 TODO break;
10843 case XML_SCHEMA_TYPE_ALL:
10844 TODO break;
10845 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10846 TODO break;
10847 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10848 TODO break;
10849 case XML_SCHEMA_TYPE_UR:
10850 TODO break;
10851 case XML_SCHEMA_TYPE_RESTRICTION:
10852 /*xmlSchemaValidateRestrictionType(ctxt, node); */
10853 TODO break;
10854 case XML_SCHEMA_TYPE_EXTENSION:
10855 TODO break;
10856 case XML_SCHEMA_TYPE_ATTRIBUTE:
10857 TODO break;
10858 case XML_SCHEMA_TYPE_GROUP:
10859 TODO break;
10860 case XML_SCHEMA_TYPE_NOTATION:
10861 TODO break;
10862 case XML_SCHEMA_TYPE_LIST:
10863 TODO break;
10864 case XML_SCHEMA_TYPE_UNION:
10865 TODO break;
10866 case XML_SCHEMA_FACET_MININCLUSIVE:
10867 TODO break;
10868 case XML_SCHEMA_FACET_MINEXCLUSIVE:
10869 TODO break;
10870 case XML_SCHEMA_FACET_MAXINCLUSIVE:
10871 TODO break;
10872 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
10873 TODO break;
10874 case XML_SCHEMA_FACET_TOTALDIGITS:
10875 TODO break;
10876 case XML_SCHEMA_FACET_FRACTIONDIGITS:
10877 TODO break;
10878 case XML_SCHEMA_FACET_PATTERN:
10879 TODO break;
10880 case XML_SCHEMA_FACET_ENUMERATION:
10881 TODO break;
10882 case XML_SCHEMA_FACET_WHITESPACE:
10883 TODO break;
10884 case XML_SCHEMA_FACET_LENGTH:
10885 TODO break;
10886 case XML_SCHEMA_FACET_MAXLENGTH:
10887 TODO break;
10888 case XML_SCHEMA_FACET_MINLENGTH:
10889 TODO break;
10890 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
10891 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000010892 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
10893 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000010894 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010895
10896 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010897 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010898 ctxt->node = ctxt->node->next;
10899 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010900 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010901}
10902
10903/**
10904 * xmlSchemaValidateType:
10905 * @ctxt: a schema validation context
10906 * @elem: an element
10907 * @type: the list of type declarations
10908 *
10909 * Validate the content of an element against the types.
10910 *
10911 * Returns 0 if the element is schemas valid, a positive error code
10912 * number otherwise and -1 in case of internal or API error.
10913 */
10914static int
10915xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010916 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
10917{
Daniel Veillard4255d502002-04-16 15:50:10 +000010918 xmlChar *nil;
10919
Daniel Veillard2db8c122003-07-08 12:16:59 +000010920 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010921 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000010922
Daniel Veillard3646d642004-06-02 19:19:14 +000010923 /* This one is called by "xmlSchemaValidateElementType" and
10924 * "xmlSchemaValidateElement".
10925 */
10926
Daniel Veillard4255d502002-04-16 15:50:10 +000010927 /*
10928 * 3.3.4 : 2
10929 */
10930 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +000010931 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10932 "Element declaration %s is abstract\n",
10933 elemDecl->name, NULL);
10934 /* Changed, since the element declaration is abstract and not
10935 * the element itself. */
10936 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
10937 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010938 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010939 }
10940 /*
10941 * 3.3.4: 3
10942 */
10943 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
10944 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010945 /* 3.3.4: 3.2 */
10946 if (xmlStrEqual(nil, BAD_CAST "true")) {
10947 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010948 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
10949 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010950 return (ctxt->err);
10951 }
10952 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
10953 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000010954 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
10955 "Empty element %s cannot get a fixed value\n",
10956 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010957 return (ctxt->err);
10958 }
10959 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010960 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010961 /* 3.3.4: 3.1 */
10962 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000010963 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
10964 "Element %s with xs:nil but not nillable\n",
10965 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010966 xmlFree(nil);
10967 return (ctxt->err);
10968 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010969 }
10970
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010971 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000010972
10973 ctxt->type = elemDecl->subtypes;
10974 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010975 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010976 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000010977}
10978
10979
10980/**
10981 * xmlSchemaValidateAttributes:
10982 * @ctxt: a schema validation context
10983 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000010984 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000010985 *
10986 * Validate the attributes of an element.
10987 *
10988 * Returns 0 if the element is schemas valid, a positive error code
10989 * number otherwise and -1 in case of internal or API error.
10990 */
10991static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010992xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010993{
Daniel Veillard3646d642004-06-02 19:19:14 +000010994 int ret;
10995 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000010996 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000010997 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000010998 xmlSchemaAttributeLinkPtr attrUse;
10999 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011000 int found;
William M. Brack803812b2004-06-03 02:11:24 +000011001 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011002#ifdef DEBUG_ATTR_VALIDATION
11003 int redundant = 0;
11004#endif
11005 if (type->type != XML_SCHEMA_TYPE_COMPLEX) {
11006 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_INTERNAL,
11007 "Internal error: xmlSchemaValidateAttributes: "
11008 "given type \"%s\"is not a complexType\n",
11009 type->name, NULL);
11010 return(-1);
11011 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011012
Daniel Veillard3646d642004-06-02 19:19:14 +000011013 if ((type->attributeUses == NULL) && (type->attributeWildcard == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011014 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011015
11016 attrUse = type->attributeUses;
11017
11018 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011019 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011020 attrDecl = attrUse->attr;
11021#ifdef DEBUG_ATTR_VALIDATION
11022 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
11023 printf("attr use - use: %d\n", attrDecl->occurs);
11024#endif
11025 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
11026
11027 if (curState->decl == attrUse->attr) {
11028#ifdef DEBUG_ATTR_VALIDATION
11029 redundant = 1;
11030#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011031 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011032 attr = curState->attr;
11033#ifdef DEBUG_ATTR_VALIDATION
11034 printf("attr - name: %s\n", attr->name);
11035 if (attr->ns != NULL)
11036 printf("attr - ns: %s\n", attr->ns->href);
11037 else
11038 printf("attr - ns: none\n");
11039#endif
11040 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011041 if (attr == NULL)
11042 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011043 if (attrDecl->ref != NULL) {
11044 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011045 continue;
11046 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011047 if ((attrDecl->refNs == NULL) ||
11048 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011049 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011050 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011051 continue;
11052 }
11053 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011054 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011055 continue;
11056 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011057 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011058 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011059 if (attr->ns == NULL) {
11060 /*
William M. Bracke7091952004-05-11 15:09:58 +000011061 * accept an unqualified attribute only if the target
11062 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011063 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011064 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000011065 /*
11066 * This check was removed, since the target namespace
11067 * was evaluated during parsing and already took
11068 * "attributeFormDefault" into account.
11069 */
11070 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011071 continue;
11072 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011073 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011074 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000011075 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011076 attr->ns->href))
11077 continue;
11078 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011079 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011080#ifdef DEBUG_ATTR_VALIDATION
11081 printf("found\n");
11082#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011083 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000011084 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011085 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000011086
Daniel Veillard3646d642004-06-02 19:19:14 +000011087 if (attrDecl->subtypes == NULL) {
11088 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
11089 curState->decl = attrDecl;
11090 /*
11091 * This could be put into "xmlSchemaCheckAttributes" as well, but
11092 * since it reports an internal error, it better stays here to ease
11093 * debugging.
11094 */
William M. Bracke7091952004-05-11 15:09:58 +000011095 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
11096 "Internal error: attribute %s type not resolved\n",
11097 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011098 continue;
11099 }
11100 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011101 ctxt->type = attrDecl->subtypes;
11102 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1);
11103 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000011104 if (ret != 0)
11105 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
11106 else
11107 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11108 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011109 if (value != NULL) {
11110 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000011111 }
11112 }
11113 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11114 xmlSchemaAttrStatePtr tmp;
11115
11116#ifdef DEBUG_ATTR_VALIDATION
11117 printf("required attr not found\n");
11118#endif
11119 /*
11120 * Add a new dummy attribute state.
11121 */
11122 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
11123 if (tmp == NULL) {
11124 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
11125 return (-1);
11126 }
11127 tmp->attr = NULL;
11128 tmp->state = XML_SCHEMAS_ATTR_MISSING;
11129 tmp->decl = attrDecl;
11130 tmp->next = NULL;
11131
11132 if (reqAttrStates == NULL) {
11133 reqAttrStates = tmp;
11134 reqAttrStatesTop = tmp;
11135 } else {
11136 reqAttrStatesTop->next = tmp;
11137 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011138 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011139
11140 }
11141 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011142 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011143 /*
11144 * Add required attributes to the attribute states of the context.
11145 */
11146 if (reqAttrStates != NULL) {
11147 if (ctxt->attr == NULL) {
11148 ctxt->attr = reqAttrStates;
11149 } else {
11150 ctxt->attrTop->next = reqAttrStates;
11151 }
11152 ctxt->attrTop = reqAttrStatesTop;
11153 }
11154 /*
11155 * Process wildcards.
11156 */
11157 if (type->attributeWildcard != NULL) {
11158#ifdef DEBUG_ATTR_VALIDATION
11159 xmlSchemaWildcardNsPtr ns;
11160 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011161 if (type->attributeWildcard->processContents ==
11162 XML_SCHEMAS_ANY_LAX)
11163 printf("processContents: lax\n");
11164 else if (type->attributeWildcard->processContents ==
11165 XML_SCHEMAS_ANY_STRICT)
11166 printf("processContents: strict\n");
11167 else
11168 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000011169 if (type->attributeWildcard->any)
11170 printf("type: any\n");
11171 else if (type->attributeWildcard->negNsSet != NULL) {
11172 printf("type: negated\n");
11173 if (type->attributeWildcard->negNsSet->value == NULL)
11174 printf("ns: (absent)\n");
11175 else
11176 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
11177 } else if (type->attributeWildcard->nsSet != NULL) {
11178 printf("type: set\n");
11179 ns = type->attributeWildcard->nsSet;
11180 while (ns != NULL) {
11181 if (ns->value == NULL)
11182 printf("ns: (absent)\n");
11183 else
11184 printf("ns: %s\n", ns->value);
11185 ns = ns->next;
11186 }
11187 } else
11188 printf("empty\n");
11189
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011190
11191#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000011192 curState = ctxt->attr;
11193 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011194 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
11195 if (curState->attr->ns != NULL)
11196 nsURI = curState->attr->ns->href;
11197 else
11198 nsURI = NULL;
11199 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11200 nsURI)) {
11201 /*
11202 * Handle processContents.
11203 */
11204 if ((type->attributeWildcard->processContents ==
11205 XML_SCHEMAS_ANY_LAX) ||
11206 (type->attributeWildcard->processContents ==
11207 XML_SCHEMAS_ANY_STRICT)) {
11208
11209 attr = curState->attr;
11210 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
11211 attr->name, nsURI);
11212 if (attrDecl != NULL) {
11213 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011214 ctxt->type = attrDecl->subtypes;
11215 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1);
11216 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011217 if (ret != 0)
11218 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
11219 else
11220 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11221 curState->decl = attrDecl;
11222 if (value != NULL) {
11223 xmlFree(value);
11224 }
11225
11226 } else if (type->attributeWildcard->processContents ==
11227 XML_SCHEMAS_ANY_LAX) {
11228 curState->state = XML_SCHEMAS_ATTR_CHECKED;
11229 }
11230 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000011231 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000011232 }
11233 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011234 curState = curState->next;
11235 }
11236 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011237#ifdef DEBUG_ATTR_VALIDATION
11238 if (redundant)
11239 xmlGenericError(xmlGenericErrorContext,
11240 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
11241 type->name);
11242#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011243 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011244}
11245
11246/**
11247 * xmlSchemaValidateElement:
11248 * @ctxt: a schema validation context
11249 * @elem: an element
11250 *
11251 * Validate an element in a tree
11252 *
11253 * Returns 0 if the element is schemas valid, a positive error code
11254 * number otherwise and -1 in case of internal or API error.
11255 */
11256static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
11258{
Daniel Veillard4255d502002-04-16 15:50:10 +000011259 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000011260 int ret;
11261 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011262
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011263 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011264 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11265 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011266 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011267 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11268 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011269 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011270 /* This one is called by xmlSchemaValidateDocument only. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011271
Daniel Veillard4255d502002-04-16 15:50:10 +000011272 /*
11273 * 3.3.4 : 1
11274 */
11275 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011276 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11277 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011278 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011279 }
11280 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011281 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
11282 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011283 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011284 }
11285 /*
11286 * Verify the attributes
11287 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011288 attrs = ctxt->attr;
11289 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000011290 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillard4255d502002-04-16 15:50:10 +000011291 /*
11292 * Verify the element content recursively
11293 */
11294 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
11296 (xmlRegExecCallbacks)
11297 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011298#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011300#endif
11301 }
11302 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011303 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011304 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011305#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 xmlGenericError(xmlGenericErrorContext,
11307 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011308#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011310 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11311 "Element %s content check failed\n",
11312 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011313 } else if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011314 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ELEMCONT,
11315 "Element %s content check failed\n",
11316 elem->name, NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011317#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011318 } else {
11319 xmlGenericError(xmlGenericErrorContext,
11320 "Element %s content check succeeded\n",
11321 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011322
11323#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011324 }
11325 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000011326 }
11327 /*
11328 * Verify that all attributes were Schemas-validated
11329 */
11330 xmlSchemaCheckAttributes(ctxt, elem);
Daniel Veillard3646d642004-06-02 19:19:14 +000011331 if (ctxt->attr != NULL)
11332 xmlSchemaFreeAttributeStates(ctxt->attr);
11333 ctxt->attr = attrs;
11334 ctxt->attrTop = attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335
11336 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011337}
11338
11339/**
11340 * xmlSchemaValidateDocument:
11341 * @ctxt: a schema validation context
11342 * @doc: a parsed document tree
11343 *
11344 * Validate a document tree in memory.
11345 *
11346 * Returns 0 if the document is schemas valid, a positive error code
11347 * number otherwise and -1 in case of internal or API error.
11348 */
11349static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11351{
Daniel Veillard4255d502002-04-16 15:50:10 +000011352 xmlNodePtr root;
11353 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011354
Daniel Veillard4255d502002-04-16 15:50:10 +000011355 root = xmlDocGetRootElement(doc);
11356 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011357 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
11358 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011359 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011360 }
William M. Bracke7091952004-05-11 15:09:58 +000011361
Daniel Veillard4255d502002-04-16 15:50:10 +000011362 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011363 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11364 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011365 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011366 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11367 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011368
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011369 /*
11370 * special case whe elementFormDefault is unqualified for top-level elem.
11371 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011372 /* Removed, since elementFormDefault does not apply to top level
11373 * elements */
11374 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011375 if ((elemDecl == NULL) && (root->ns != NULL) &&
11376 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
11377 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
11378 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
11379 root->name, NULL, NULL);
11380 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011381 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011382
Daniel Veillard4255d502002-04-16 15:50:10 +000011383 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000011384 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
11385 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011386 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011387 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000011388 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011389 }
11390 /*
11391 * Okay, start the recursive validation
11392 */
11393 xmlSchemaValidateElement(ctxt, root);
11394
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011395 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011396}
11397
11398/************************************************************************
11399 * *
11400 * SAX Validation code *
11401 * *
11402 ************************************************************************/
11403
11404/************************************************************************
11405 * *
11406 * Validation interfaces *
11407 * *
11408 ************************************************************************/
11409
11410/**
11411 * xmlSchemaNewValidCtxt:
11412 * @schema: a precompiled XML Schemas
11413 *
11414 * Create an XML Schemas validation context based on the given schema
11415 *
11416 * Returns the validation context or NULL in case of error
11417 */
11418xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011419xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
11420{
Daniel Veillard4255d502002-04-16 15:50:10 +000011421 xmlSchemaValidCtxtPtr ret;
11422
11423 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
11424 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011425 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011426 return (NULL);
11427 }
11428 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
11429 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000011430 /*
11431 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011432 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011433 /* ret->attrNr = 0; */
11434 /* ret->attrMax = 10; */
11435 /* ret->attrBase = NULL; */
11436 ret->attrTop = NULL;
11437 ret->attr = NULL;
11438 /*
11439 * Removed due to changes of the attribute state list.
William M. Brack803812b2004-06-03 02:11:24 +000011440 *
Daniel Veillard4255d502002-04-16 15:50:10 +000011441 ret->attr = (xmlSchemaAttrStatePtr) xmlMalloc(ret->attrMax *
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011442 sizeof
11443 (xmlSchemaAttrState));
Daniel Veillard4255d502002-04-16 15:50:10 +000011444 if (ret->attr == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011445 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
11446 free(ret);
11447 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011448 }
11449 memset(ret->attr, 0, ret->attrMax * sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +000011450 */
11451
Daniel Veillard4255d502002-04-16 15:50:10 +000011452 return (ret);
11453}
11454
11455/**
11456 * xmlSchemaFreeValidCtxt:
11457 * @ctxt: the schema validation context
11458 *
11459 * Free the resources associated to the schema validation context
11460 */
11461void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011462xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
11463{
Daniel Veillard4255d502002-04-16 15:50:10 +000011464 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011465 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011466 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011467 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000011468 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011469 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000011470 xmlFree(ctxt);
11471}
11472
11473/**
11474 * xmlSchemaSetValidErrors:
11475 * @ctxt: a schema validation context
11476 * @err: the error function
11477 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000011478 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000011479 *
11480 * Set the error and warning callback informations
11481 */
11482void
11483xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011484 xmlSchemaValidityErrorFunc err,
11485 xmlSchemaValidityWarningFunc warn, void *ctx)
11486{
Daniel Veillard4255d502002-04-16 15:50:10 +000011487 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011488 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011489 ctxt->error = err;
11490 ctxt->warning = warn;
11491 ctxt->userData = ctx;
11492}
11493
11494/**
11495 * xmlSchemaValidateDoc:
11496 * @ctxt: a schema validation context
11497 * @doc: a parsed document tree
11498 *
11499 * Validate a document tree in memory.
11500 *
11501 * Returns 0 if the document is schemas valid, a positive error code
11502 * number otherwise and -1 in case of internal or API error.
11503 */
11504int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011505xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
11506{
Daniel Veillard4255d502002-04-16 15:50:10 +000011507 int ret;
11508
11509 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011510 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011511
11512 ctxt->doc = doc;
11513 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011514 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000011515}
11516
11517/**
11518 * xmlSchemaValidateStream:
11519 * @ctxt: a schema validation context
11520 * @input: the input to use for reading the data
11521 * @enc: an optional encoding information
11522 * @sax: a SAX handler for the resulting events
11523 * @user_data: the context to provide to the SAX handler.
11524 *
11525 * Validate a document tree in memory.
11526 *
11527 * Returns 0 if the document is schemas valid, a positive error code
11528 * number otherwise and -1 in case of internal or API error.
11529 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011530int
Daniel Veillard4255d502002-04-16 15:50:10 +000011531xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011532 xmlParserInputBufferPtr input, xmlCharEncoding enc,
11533 xmlSAXHandlerPtr sax, void *user_data)
11534{
Daniel Veillard4255d502002-04-16 15:50:10 +000011535 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011536 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011537 ctxt->input = input;
11538 ctxt->enc = enc;
11539 ctxt->sax = sax;
11540 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011541 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011542}
11543
11544#endif /* LIBXML_SCHEMAS_ENABLED */