blob: a7e8d5e76b1011fcb86524bf012067965c7b00e6 [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 Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
79 "ST";
80static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
81 "CT";
82
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
94#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
95#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
96#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
97
Daniel Veillard4255d502002-04-16 15:50:10 +000098#define XML_SCHEMAS_PARSE_ERROR 1
99
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000100#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
101
Daniel Veillard4255d502002-04-16 15:50:10 +0000102struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000103 void *userData; /* user specific data block */
104 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
105 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000106 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000107 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000108 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000109
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000110 xmlSchemaPtr topschema; /* The main schema */
111 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
112
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000113 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000114 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000115 int counter;
116
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000117 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000118 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000119 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000120
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000121 const char *buffer;
122 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000123
Daniel Veillard4255d502002-04-16 15:50:10 +0000124 /*
125 * Used to build complex element content models
126 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000127 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000128 xmlAutomataStatePtr start;
129 xmlAutomataStatePtr end;
130 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000131
132 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000133 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000134 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
135 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Daniel Veillard4255d502002-04-16 15:50:10 +0000136};
137
138
139#define XML_SCHEMAS_ATTR_UNKNOWN 1
140#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000141#define XML_SCHEMAS_ATTR_PROHIBITED 3
142#define XML_SCHEMAS_ATTR_MISSING 4
143#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
144#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Daniel Veillard4255d502002-04-16 15:50:10 +0000145
146typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
147typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
148struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000149 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000150 xmlAttrPtr attr;
151 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000152 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +0000153};
154
155/**
156 * xmlSchemaValidCtxt:
157 *
158 * A Schemas validation context
159 */
160
161struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000162 void *userData; /* user specific data block */
163 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
164 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000165 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000166
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000167 xmlSchemaPtr schema; /* The schema in use */
168 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000169 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000170 xmlCharEncoding enc;
171 xmlSAXHandlerPtr sax;
172 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000173
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000174 xmlDocPtr myDoc;
175 int err;
176 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000177
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000178 xmlNodePtr node;
179 xmlNodePtr cur;
180 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000181
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182 xmlRegExecCtxtPtr regexp;
183 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000184
Daniel Veillard3646d642004-06-02 19:19:14 +0000185 xmlSchemaAttrStatePtr attrTop;
186 /* xmlSchemaAttrStatePtr attrBase; */
187 /* int attrMax; */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000188 xmlSchemaAttrStatePtr attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000189 xmlNodePtr scope;
190 int valueWS;
Daniel Veillard4255d502002-04-16 15:50:10 +0000191};
192
Daniel Veillard1d913862003-11-21 00:28:39 +0000193/*
194 * These are the entries in the schemas importSchemas hash table
195 */
196typedef struct _xmlSchemaImport xmlSchemaImport;
197typedef xmlSchemaImport *xmlSchemaImportPtr;
198struct _xmlSchemaImport {
199 const xmlChar *schemaLocation;
200 xmlSchemaPtr schema;
William M. Brack2f2a6632004-08-20 23:09:47 +0000201 xmlDocPtr doc;
Daniel Veillard1d913862003-11-21 00:28:39 +0000202};
Daniel Veillard4255d502002-04-16 15:50:10 +0000203
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000204/*
205 * These are the entries associated to includes in a schemas
206 */
207typedef struct _xmlSchemaInclude xmlSchemaInclude;
208typedef xmlSchemaInclude *xmlSchemaIncludePtr;
209struct _xmlSchemaInclude {
210 xmlSchemaIncludePtr next;
211
212 const xmlChar *schemaLocation;
213 xmlDocPtr doc;
214};
215
Daniel Veillard4255d502002-04-16 15:50:10 +0000216/************************************************************************
217 * *
218 * Some predeclarations *
219 * *
220 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000221
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000222static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
223 xmlSchemaPtr schema,
224 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000225static void
226xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
227 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
228static const char *
229xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
230static int
231xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
232 const xmlChar *value,
233 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000234 int applyFacets,
235 int normalize);
William M. Brack2f2a6632004-08-20 23:09:47 +0000236static int
237xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
238 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000239
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000240/************************************************************************
241 * *
242 * Datatype error handlers *
243 * *
244 ************************************************************************/
245
246/**
247 * xmlSchemaPErrMemory:
248 * @node: a context node
249 * @extra: extra informations
250 *
251 * Handle an out of memory condition
252 */
253static void
254xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
255 const char *extra, xmlNodePtr node)
256{
257 if (ctxt != NULL)
258 ctxt->nberrors++;
259 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
260 extra);
261}
262
263/**
264 * xmlSchemaPErr:
265 * @ctxt: the parsing context
266 * @node: the context node
267 * @error: the error code
268 * @msg: the error message
269 * @str1: extra data
270 * @str2: extra data
271 *
272 * Handle a parser error
273 */
274static void
275xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
276 const char *msg, const xmlChar * str1, const xmlChar * str2)
277{
278 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000279 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000280 void *data = NULL;
281
282 if (ctxt != NULL) {
283 ctxt->nberrors++;
284 channel = ctxt->error;
285 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000286 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000287 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000288 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000289 error, XML_ERR_ERROR, NULL, 0,
290 (const char *) str1, (const char *) str2, NULL, 0, 0,
291 msg, str1, str2);
292}
293
294/**
295 * xmlSchemaPErr2:
296 * @ctxt: the parsing context
297 * @node: the context node
298 * @node: the current child
299 * @error: the error code
300 * @msg: the error message
301 * @str1: extra data
302 * @str2: extra data
303 *
304 * Handle a parser error
305 */
306static void
307xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
308 xmlNodePtr child, int error,
309 const char *msg, const xmlChar * str1, const xmlChar * str2)
310{
311 if (child != NULL)
312 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
313 else
314 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
315}
316
Daniel Veillard01fa6152004-06-29 17:04:39 +0000317
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000319 * xmlSchemaPErrExt:
320 * @ctxt: the parsing context
321 * @node: the context node
322 * @error: the error code
323 * @strData1: extra data
324 * @strData2: extra data
325 * @strData3: extra data
326 * @msg: the message
327 * @str1: extra parameter for the message display
328 * @str2: extra parameter for the message display
329 * @str3: extra parameter for the message display
330 * @str4: extra parameter for the message display
331 * @str5: extra parameter for the message display
332 *
333 * Handle a parser error
334 */
335static void
336xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
337 const xmlChar * strData1, const xmlChar * strData2,
338 const xmlChar * strData3, const char *msg, const xmlChar * str1,
339 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
340 const xmlChar * str5)
341{
342
343 xmlGenericErrorFunc channel = NULL;
344 xmlStructuredErrorFunc schannel = NULL;
345 void *data = NULL;
346
347 if (ctxt != NULL) {
348 ctxt->nberrors++;
349 channel = ctxt->error;
350 data = ctxt->userData;
351 schannel = ctxt->serror;
352 }
353 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
354 error, XML_ERR_ERROR, NULL, 0,
355 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000356 (const char *) strData3, 0, 0, msg, str1, str2,
357 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000358}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000359
Daniel Veillard3646d642004-06-02 19:19:14 +0000360
361/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000362 * xmlSchemaVTypeErrMemory:
363 * @node: a context node
364 * @extra: extra informations
365 *
366 * Handle an out of memory condition
367 */
368static void
369xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
370 const char *extra, xmlNodePtr node)
371{
372 if (ctxt != NULL) {
373 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000374 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000375 }
376 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
377 extra);
378}
379
380/**
381 * xmlSchemaVErr3:
382 * @ctxt: the validation context
383 * @node: the context node
384 * @error: the error code
385 * @msg: the error message
386 * @str1: extra data
387 * @str2: extra data
388 * @str3: extra data
389 *
390 * Handle a validation error
391 */
392static void
393xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
394 const char *msg, const xmlChar *str1, const xmlChar *str2,
395 const xmlChar *str3)
396{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000397 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000398 xmlGenericErrorFunc channel = NULL;
399 void *data = NULL;
400
401 if (ctxt != NULL) {
402 ctxt->nberrors++;
403 ctxt->err = error;
404 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000405 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000406 data = ctxt->userData;
407 }
408 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000409 /* Removed, since the old schema error codes have been
410 * substituted for the global error codes.
411 *
412 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
413 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000414 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000415 error, XML_ERR_ERROR, NULL, 0,
416 (const char *) str1, (const char *) str2,
417 (const char *) str3, 0, 0,
418 msg, str1, str2, str3);
419}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000420
421/**
422 * xmlSchemaVErrExt:
423 * @ctxt: the validation context
424 * @node: the context node
425 * @error: the error code
426 * @msg: the message
427 * @str1: extra parameter for the message display
428 * @str2: extra parameter for the message display
429 * @str3: extra parameter for the message display
430 * @str4: extra parameter for the message display
431 * @str5: extra parameter for the message display
432 *
433 * Handle a validation error
434 */
435static void
436xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
437 const char *msg, const xmlChar * str1,
438 const xmlChar * str2, const xmlChar * str3,
439 const xmlChar * str4, const xmlChar * str5)
440{
441 xmlStructuredErrorFunc schannel = NULL;
442 xmlGenericErrorFunc channel = NULL;
443 void *data = NULL;
444
445 if (ctxt != NULL) {
446 ctxt->nberrors++;
447 ctxt->err = error;
448 channel = ctxt->error;
449 schannel = ctxt->serror;
450 data = ctxt->userData;
451 }
452 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000453 /* Removed, since the old schema error codes have been
454 * substituted for the global error codes.
455 *
456 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
457 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000458 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
459 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
460 msg, str1, str2, str3, str4, str5);
461}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000462/**
463 * xmlSchemaVErr:
464 * @ctxt: the validation context
465 * @node: the context node
466 * @error: the error code
467 * @msg: the error message
468 * @str1: extra data
469 * @str2: extra data
470 *
471 * Handle a validation error
472 */
473static void
474xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
475 const char *msg, const xmlChar * str1, const xmlChar * str2)
476{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000477 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000478 xmlGenericErrorFunc channel = NULL;
479 void *data = NULL;
480
481 if (ctxt != NULL) {
482 ctxt->nberrors++;
483 ctxt->err = error;
484 channel = ctxt->error;
485 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000486 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000487 }
488 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000489 /* Removed, since the old schema error codes have been
490 * substituted for the global error codes.
491 *
492 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
493 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000494 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000495 error, XML_ERR_ERROR, NULL, 0,
496 (const char *) str1, (const char *) str2, NULL, 0, 0,
497 msg, str1, str2);
498}
Daniel Veillard4255d502002-04-16 15:50:10 +0000499
Daniel Veillardc0826a72004-08-10 14:17:33 +0000500/**
501 * xmlSchemaGetOnymousTypeName:
502 * @attr: the attribute declaration/use
503 *
504 * Returns the name of the attribute; if the attribute
505 * is a reference, the name of the referenced global type will be returned.
506 */
507static const xmlChar *
508xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
509{
510 if (attr->ref != NULL)
511 return(attr->ref);
512 else
513 return(attr->name);
514}
515
516/**
517 * xmlSchemaGetOnymousTargetNsURI:
518 * @type: the type (element or attribute)
519 *
520 * Returns the target namespace URI of the type; if the type is a reference,
521 * the target namespace of the referenced type will be returned.
522 */
523static const xmlChar *
524xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
525{
526 if (attr->ref != NULL)
527 return (attr->refNs);
528 else
529 return(attr->targetNamespace);
530}
531
532/**
533 * xmlSchemaFormatNsUriLocal:
534 * @buf: the string buffer
535 * @uri: the namespace URI
536 * @local: the local name
537 *
538 * Returns a representation of the given URI used
539 * for error reports.
540 *
541 * Returns an empty string, if @ns is NULL, a formatted
542 * string otherwise.
543 */
544static const xmlChar*
545xmlSchemaFormatNsUriLocal(xmlChar **buf,
546 const xmlChar *uri, const xmlChar *local)
547{
548 if (*buf != NULL)
549 xmlFree(*buf);
550 if (uri == NULL) {
551 *buf = xmlStrdup(BAD_CAST "{'");
552 *buf = xmlStrcat(*buf, local);
553 } else {
554 *buf = xmlStrdup(BAD_CAST "{'");
555 *buf = xmlStrcat(*buf, uri);
556 *buf = xmlStrcat(*buf, BAD_CAST "', '");
557 *buf = xmlStrcat(*buf, local);
558 }
559 *buf = xmlStrcat(*buf, BAD_CAST "'}");
560 return ((const xmlChar *) *buf);
561}
562
563/**
564 * xmlSchemaFormatNsPrefixLocal:
565 * @buf: the string buffer
566 * @ns: the namespace
567 * @local: the local name
568 *
569 * Returns a representation of the given URI used
570 * for error reports.
571 *
572 * Returns an empty string, if @ns is NULL, a formatted
573 * string otherwise.
574 */
575static const xmlChar*
576xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
577 xmlNsPtr ns, const xmlChar *local)
578{
579 if (*buf != NULL) {
580 xmlFree(*buf);
581 *buf = NULL;
582 }
583 if ((ns == NULL) || (ns->prefix == NULL))
584 return(local);
585 else {
586 *buf = xmlStrdup(ns->prefix);
587 *buf = xmlStrcat(*buf, BAD_CAST ":");
588 *buf = xmlStrcat(*buf, local);
589 }
590 return ((const xmlChar *) *buf);
591}
592
593/**
594 * xmlSchemaFormatItemForReport:
595 * @buf: the string buffer
596 * @itemDes: the designation of the item
597 * @itemName: the name of the item
598 * @item: the item as an object
599 * @itemNode: the node of the item
600 * @local: the local name
601 * @parsing: if the function is used during the parse
602 *
603 * Returns a representation of the given item used
604 * for error reports.
605 *
606 * The following order is used to build the resulting
607 * designation if the arguments are not NULL:
608 * 1a. If itemDes not NULL -> itemDes
609 * 1b. If (itemDes not NULL) and (itemName not NULL)
610 * -> itemDes + itemName
611 * 2. If the preceding was NULL and (item not NULL) -> item
612 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
613 *
614 * If the itemNode is an attribute node, the name of the attribute
615 * will be appended to the result.
616 *
617 * Returns the formatted string and sets @buf to the resulting value.
618 */
619static xmlChar*
620xmlSchemaFormatItemForReport(xmlChar **buf,
621 const xmlChar *itemDes,
622 xmlSchemaTypePtr item,
623 xmlNodePtr itemNode,
624 int parsing)
625{
626 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000627 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000628
629 if (*buf != NULL) {
630 xmlFree(*buf);
631 *buf = NULL;
632 }
633
William M. Brack2f2a6632004-08-20 23:09:47 +0000634 if (itemDes != NULL) {
635 *buf = xmlStrdup(itemDes);
636 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000637 if (item->type == XML_SCHEMA_TYPE_BASIC) {
638 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
639 *buf = xmlStrdup(BAD_CAST "'anyType'");
640 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
641 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
642 else {
643 /* *buf = xmlStrdup(BAD_CAST "bi "); */
644 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
645 *buf = xmlStrdup(BAD_CAST "'");
646 *buf = xmlStrcat(*buf, item->name);
647 *buf = xmlStrcat(*buf, BAD_CAST "'");
648 }
649 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
650 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
651 *buf = xmlStrdup(xmlSchemaElemDesST);
652 *buf = xmlStrcat(*buf, BAD_CAST " '");
653 *buf = xmlStrcat(*buf, item->name);
654 *buf = xmlStrcat(*buf, BAD_CAST "'");
655 } else {
656 *buf = xmlStrdup(xmlSchemaElemDesST);
657 *buf = xmlStrcat(*buf, BAD_CAST " local");
658 }
659 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
660 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
661 *buf = xmlStrdup(xmlSchemaElemDesCT);
662 *buf = xmlStrcat(*buf, BAD_CAST " '");
663 *buf = xmlStrcat(*buf, item->name);
664 *buf = xmlStrcat(*buf, BAD_CAST "'");
665 } else {
666 *buf = xmlStrdup(xmlSchemaElemDesCT);
667 *buf = xmlStrcat(*buf, BAD_CAST " local");
668 }
669 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
670 xmlSchemaAttributePtr attr;
671
672 attr = (xmlSchemaAttributePtr) item;
673 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
674 (attr->ref == NULL)) {
675 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
676 *buf = xmlStrcat(*buf, BAD_CAST " '");
677 *buf = xmlStrcat(*buf, attr->name);
678 *buf = xmlStrcat(*buf, BAD_CAST "'");
679 } else {
680 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
681 *buf = xmlStrcat(*buf, BAD_CAST " '");
682 *buf = xmlStrcat(*buf, attr->refPrefix);
683 *buf = xmlStrcat(*buf, BAD_CAST ":");
684 *buf = xmlStrcat(*buf, attr->ref);
685 *buf = xmlStrcat(*buf, BAD_CAST "'");
686 }
687 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
688 xmlSchemaElementPtr elem;
689
690 elem = (xmlSchemaElementPtr) item;
691 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
692 (elem->ref == NULL)) {
693 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
694 *buf = xmlStrcat(*buf, BAD_CAST " '");
695 *buf = xmlStrcat(*buf, elem->name);
696 *buf = xmlStrcat(*buf, BAD_CAST "'");
697 } else {
698 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
699 *buf = xmlStrcat(*buf, BAD_CAST " '");
700 *buf = xmlStrcat(*buf, elem->refPrefix);
701 *buf = xmlStrcat(*buf, BAD_CAST ":");
702 *buf = xmlStrcat(*buf, elem->ref);
703 *buf = xmlStrcat(*buf, BAD_CAST "'");
704 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000705 } else
706 named = 0;
707 } else
708 named = 0;
709
710 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000711 xmlNodePtr elem;
712
713 if (itemNode->type == XML_ATTRIBUTE_NODE)
714 elem = itemNode->parent;
715 else
716 elem = itemNode;
717 *buf = xmlStrdup(BAD_CAST "Element '");
718 if (parsing)
719 *buf = xmlStrcat(*buf, elem->name);
720 else
721 *buf = xmlStrcat(*buf,
722 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
723 *buf = xmlStrcat(*buf, BAD_CAST "'");
724 }
725 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
726 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
727 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
728 itemNode->ns, itemNode->name));
729 *buf = xmlStrcat(*buf, BAD_CAST "'");
730 }
731 FREE_AND_NULL(str);
732
733 return (*buf);
734}
735
736/**
737 * xmlSchemaPFormatItemDes:
738 * @buf: the string buffer
739 * @item: the item as a schema object
740 * @itemNode: the item as a node
741 *
742 * If the pointer to @buf is not NULL and @but holds no value,
743 * the value is set to a item designation using
744 * xmlSchemaFormatItemForReport. This one avoids adding
745 * an attribute designation postfix.
746 *
747 * Returns a string of all enumeration elements.
748 */
749static void
750xmlSchemaPRequestItemDes(xmlChar **buf,
751 xmlSchemaTypePtr item,
752 xmlNodePtr itemNode)
753{
754 if ((buf == 0) || (*buf != NULL))
755 return;
756 if (itemNode->type == XML_ATTRIBUTE_NODE)
757 itemNode = itemNode->parent;
758 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
759}
760
761/**
762 * xmlSchemaFormatFacetEnumSet:
763 * @buf: the string buffer
764 * @type: the type holding the enumeration facets
765 *
766 * Builds a string consisting of all enumeration elements.
767 *
768 * Returns a string of all enumeration elements.
769 */
770static const xmlChar *
771xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
772{
773 xmlSchemaFacetLinkPtr link;
774
775 if (*buf != NULL)
776 xmlFree(*buf);
777 *buf = NULL;
778 for (link = type->facetSet; link != NULL; link = link->next) {
779 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
780 if (*buf == NULL) {
781 *buf = xmlStrdup(BAD_CAST "'");
782 *buf = xmlStrcat(*buf, link->facet->value);
783 *buf = xmlStrcat(*buf, BAD_CAST "'");
784 } else {
785 *buf = xmlStrcat(*buf, BAD_CAST ", '");
786 *buf = xmlStrcat(*buf, link->facet->value);
787 *buf = xmlStrcat(*buf, BAD_CAST "'");
788 }
789 }
790 }
791 return ((const xmlChar *) *buf);
792}
793
794/**
795 * xmlSchemaVFacetErr:
796 * @ctxt: the schema validation context
797 * @error: the error code
798 * @node: the node to be validated
799 * @value: the value of the node
800 * @type: the type holding the facet
801 * @facet: the facet
802 * @message: the error message of NULL
803 * @str1: extra data
804 * @str2: extra data
805 * @str3: extra data
806 *
807 * Reports a facet validation error.
808 * TODO: Should this report the value of an element as well?
809 */
810static void
811xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
812 xmlParserErrors error,
813 xmlNodePtr node,
814 const xmlChar *value,
815 unsigned long length,
816 xmlSchemaTypePtr type,
817 xmlSchemaFacetPtr facet,
818 const char *message,
819 const xmlChar *str1,
820 const xmlChar *str2,
821 const xmlChar *str3)
822{
823 xmlChar *str = NULL, *msg = NULL;
824 xmlSchemaTypeType facetType;
825
826 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
827 msg = xmlStrcat(msg, BAD_CAST " [");
828 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
829 msg = xmlStrcat(msg, BAD_CAST ", facet '");
830 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
831 facetType = XML_SCHEMA_FACET_ENUMERATION;
832 /*
833 * If enumerations are validated, one must not expect the
834 * facet to be given.
835 */
836 } else
837 facetType = facet->type;
838 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
839 msg = xmlStrcat(msg, BAD_CAST "']: ");
840 if (message == NULL) {
841 /*
842 * Use a default message.
843 */
844 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
845 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
846 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
847
848 char len[25], actLen[25];
849
850 /* FIXME, TODO: What is the max expected string length of the
851 * this value?
852 */
853 if (node->type == XML_ATTRIBUTE_NODE)
854 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
855 else
856 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
857
858 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
859 snprintf(actLen, 24, "%lu", length);
860
861 if (facetType == XML_SCHEMA_FACET_LENGTH)
862 msg = xmlStrcat(msg,
863 BAD_CAST "this differs from the allowed length of '%s'.\n");
864 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
865 msg = xmlStrcat(msg,
866 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
867 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
868 msg = xmlStrcat(msg,
869 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
870
871 if (node->type == XML_ATTRIBUTE_NODE)
872 xmlSchemaVErrExt(ctxt, node, error,
873 (const char *) msg,
874 value, (const xmlChar *) actLen, (const xmlChar *) len,
875 NULL, NULL);
876 else
877 xmlSchemaVErr(ctxt, node, error,
878 (const char *) msg,
879 (const xmlChar *) actLen, (const xmlChar *) len);
880
881 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
882 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
883 "of the set {%s}.\n");
884 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
885 xmlSchemaFormatFacetEnumSet(&str, type));
886 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
887 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
888 "by the pattern '%s'.\n");
889 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
890 facet->value);
891 } else if (node->type == XML_ATTRIBUTE_NODE) {
892 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
893 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
894 } else {
895 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
896 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
897 }
898 } else {
899 msg = xmlStrcat(msg, (const xmlChar *) message);
900 msg = xmlStrcat(msg, BAD_CAST ".\n");
901 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
902 }
903 FREE_AND_NULL(str)
904 xmlFree(msg);
905}
906
907/**
908 * xmlSchemaVSimpleTypeErr:
909 * @ctxt: the schema validation context
910 * @error: the error code
911 * @type: the type used for validation
912 * @node: the node containing the validated value
913 * @value: the validated value
914 *
915 * Reports a simple type validation error.
916 * TODO: Should this report the value of an element as well?
917 */
918static void
919xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
920 xmlParserErrors error,
921 xmlNodePtr node,
922 const xmlChar *value,
923 xmlSchemaTypePtr type)
924{
925 xmlChar *str = NULL, *msg = NULL;
926
927 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
928 msg = xmlStrcat(msg, BAD_CAST " [");
929 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
930 if (node->type == XML_ATTRIBUTE_NODE) {
931 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
932 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
933 } else {
934 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
935 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
936 }
937 FREE_AND_NULL(str)
938 xmlFree(msg);
939}
940
941/**
William M. Brack2f2a6632004-08-20 23:09:47 +0000942 * xmlSchemaVComplexTypeErr:
943 * @ctxt: the schema validation context
944 * @error: the error code
945 * @node: the node containing the validated value
946 * @type: the complex type used for validation
947 * @message: the error message
948 *
949 * Reports a complex type validation error.
950 */
951static void
952xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
953 xmlParserErrors error,
954 xmlNodePtr node,
955 xmlSchemaTypePtr type,
956 const char *message)
957{
958 xmlChar *str = NULL, *msg = NULL;
959
960 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
961 msg = xmlStrcat(msg, BAD_CAST " [");
962 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
963 msg = xmlStrcat(msg, BAD_CAST "]: %s.\n");
964 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
965 (const xmlChar *) message, NULL);
966 FREE_AND_NULL(str)
967 xmlFree(msg);
968}
969
970/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000971 * xmlSchemaPMissingAttrErr:
972 * @ctxt: the schema validation context
973 * @ownerDes: the designation of the owner
974 * @ownerName: the name of the owner
975 * @ownerItem: the owner as a schema object
976 * @ownerElem: the owner as an element node
977 * @node: the parent element node of the missing attribute node
978 * @type: the corresponding type of the attribute node
979 *
980 * Reports an illegal attribute.
981 */
982static void
983xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
984 xmlParserErrors error,
985 xmlChar **ownerDes,
986 xmlSchemaTypePtr ownerItem,
987 xmlNodePtr ownerElem,
988 const char *name,
989 const char *message)
990{
991 xmlChar *des = NULL;
992
993 if (ownerDes == NULL)
994 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
995 else if (*ownerDes == NULL) {
996 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
997 des = *ownerDes;
998 } else
999 des = *ownerDes;
1000 if (message != NULL)
1001 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1002 else
1003 xmlSchemaPErr(ctxt, ownerElem, error,
1004 "%s: The attribute '%s' is required but missing.\n",
1005 BAD_CAST des, BAD_CAST name);
1006 if (ownerDes == NULL)
1007 FREE_AND_NULL(des);
1008}
1009
William M. Brack2f2a6632004-08-20 23:09:47 +00001010/**
1011 * xmlSchemaCompTypeToString:
1012 * @type: the type of the schema item
1013 *
1014 * Returns the component name of a schema item.
1015 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001016static const char *
1017xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1018{
1019 switch (type) {
1020 case XML_SCHEMA_TYPE_SIMPLE:
1021 return("simple type definition");
1022 case XML_SCHEMA_TYPE_COMPLEX:
1023 return("complex type definition");
1024 case XML_SCHEMA_TYPE_ELEMENT:
1025 return("element declaration");
1026 case XML_SCHEMA_TYPE_ATTRIBUTE:
1027 return("attribute declaration");
1028 case XML_SCHEMA_TYPE_GROUP:
1029 return("model group definition");
1030 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1031 return("attribute group definition");
1032 case XML_SCHEMA_TYPE_NOTATION:
1033 return("notation declaration");
1034 default:
1035 return("Not a schema component");
1036 }
1037}
1038/**
1039 * xmlSchemaPResCompAttrErr:
1040 * @ctxt: the schema validation context
1041 * @error: the error code
1042 * @ownerDes: the designation of the owner
1043 * @ownerItem: the owner as a schema object
1044 * @ownerElem: the owner as an element node
1045 * @name: the name of the attribute holding the QName
1046 * @refName: the referenced local name
1047 * @refURI: the referenced namespace URI
1048 * @message: optional message
1049 *
1050 * Used to report QName attribute values that failed to resolve
1051 * to schema components.
1052 */
1053static void
1054xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1055 xmlParserErrors error,
1056 xmlChar **ownerDes,
1057 xmlSchemaTypePtr ownerItem,
1058 xmlNodePtr ownerElem,
1059 const char *name,
1060 const xmlChar *refName,
1061 const xmlChar *refURI,
1062 xmlSchemaTypeType refType,
1063 const char *refTypeStr)
1064{
1065 xmlChar *des = NULL, *strA = NULL;
1066
1067 if (ownerDes == NULL)
1068 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1069 else if (*ownerDes == NULL) {
1070 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1071 des = *ownerDes;
1072 } else
1073 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001074 if (refTypeStr == NULL)
1075 refTypeStr = xmlSchemaCompTypeToString(refType);
1076 xmlSchemaPErrExt(ctxt, ownerElem, error,
1077 NULL, NULL, NULL,
1078 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1079 "%s.\n", BAD_CAST des, BAD_CAST name,
1080 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1081 BAD_CAST refTypeStr, NULL);
1082 if (ownerDes == NULL)
1083 FREE_AND_NULL(des)
1084 FREE_AND_NULL(strA)
1085}
1086
William M. Brack2f2a6632004-08-20 23:09:47 +00001087/**
1088 * xmlSchemaPCustomAttrErr:
1089 * @ctxt: the schema parser context
1090 * @error: the error code
1091 * @ownerDes: the designation of the owner
1092 * @ownerItem: the owner as a schema object
1093 * @attr: the illegal attribute node
1094 *
1095 * Reports an illegal attribute during the parse.
1096 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001097static void
1098xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001099 xmlParserErrors error,
1100 xmlChar **ownerDes,
1101 xmlSchemaTypePtr ownerItem,
1102 xmlAttrPtr attr,
1103 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001104{
1105 xmlChar *des = NULL;
1106
1107 if (ownerDes == NULL)
1108 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1109 else if (*ownerDes == NULL) {
1110 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1111 des = *ownerDes;
1112 } else
1113 des = *ownerDes;
1114 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1115 "%s, attribute '%s': %s.\n",
1116 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1117 if (ownerDes == NULL)
1118 FREE_AND_NULL(des);
1119}
1120
1121/**
1122 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001123 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001124 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001125 * @ownerDes: the designation of the attribute's owner
1126 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001127 * @attr: the illegal attribute node
1128 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001129 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001130 */
1131static void
1132xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1133 xmlParserErrors error,
1134 xmlChar **ownerDes,
1135 xmlSchemaTypePtr ownerItem,
1136 xmlAttrPtr attr)
1137{
1138 xmlChar *des = NULL, *strA = NULL;
1139
1140 if (ownerDes == NULL)
1141 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1142 else if (*ownerDes == NULL) {
1143 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1144 des = *ownerDes;
1145 } else
1146 des = *ownerDes;
1147 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1148 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1149 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1150 if (ownerDes == NULL)
1151 FREE_AND_NULL(des);
1152 FREE_AND_NULL(strA);
1153}
1154
William M. Brack2f2a6632004-08-20 23:09:47 +00001155/**
1156 * xmlSchemaPAquireDes:
1157 * @des: the first designation
1158 * @itemDes: the second designation
1159 * @item: the schema item
1160 * @itemElem: the node of the schema item
1161 *
1162 * Creates a designation for an item.
1163 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001164static void
1165xmlSchemaPAquireDes(xmlChar **des,
1166 xmlChar **itemDes,
1167 xmlSchemaTypePtr item,
1168 xmlNodePtr itemElem)
1169{
1170 if (itemDes == NULL)
1171 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1172 else if (*itemDes == NULL) {
1173 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1174 *des = *itemDes;
1175 } else
1176 *des = *itemDes;
1177}
1178
William M. Brack2f2a6632004-08-20 23:09:47 +00001179/**
1180 * xmlSchemaPCustomErr:
1181 * @ctxt: the schema parser context
1182 * @error: the error code
1183 * @itemDes: the designation of the schema item
1184 * @item: the schema item
1185 * @itemElem: the node of the schema item
1186 * @message: the error message
1187 * @str1: an optional param for the error message
1188 * @str2: an optional param for the error message
1189 * @str3: an optional param for the error message
1190 *
1191 * Reports an error during parsing.
1192 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001193static void
1194xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1195 xmlParserErrors error,
1196 xmlChar **itemDes,
1197 xmlSchemaTypePtr item,
1198 xmlNodePtr itemElem,
1199 const char *message,
1200 const xmlChar *str1,
1201 const xmlChar *str2,
1202 const xmlChar *str3)
1203{
1204 xmlChar *des = NULL, *msg = NULL;
1205
1206 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1207 msg = xmlStrdup(BAD_CAST "%s: ");
1208 msg = xmlStrcat(msg, (const xmlChar *) message);
1209 msg = xmlStrcat(msg, BAD_CAST ".\n");
1210 if ((itemElem == NULL) && (item != NULL))
1211 itemElem = item->node;
1212 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1213 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1214 if (itemDes == NULL)
1215 FREE_AND_NULL(des);
1216 FREE_AND_NULL(msg);
1217}
1218
William M. Brack2f2a6632004-08-20 23:09:47 +00001219/**
1220 * xmlSchemaPCustomErr:
1221 * @ctxt: the schema parser context
1222 * @error: the error code
1223 * @itemDes: the designation of the schema item
1224 * @item: the schema item
1225 * @itemElem: the node of the schema item
1226 * @message: the error message
1227 * @str1: the optional param for the error message
1228 *
1229 * Reports an error during parsing.
1230 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001231static void
1232xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1233 xmlParserErrors error,
1234 xmlChar **itemDes,
1235 xmlSchemaTypePtr item,
1236 xmlNodePtr itemElem,
1237 const char *message,
1238 const xmlChar *str1)
1239{
1240 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1241 str1, NULL, NULL);
1242}
1243
William M. Brack2f2a6632004-08-20 23:09:47 +00001244/**
1245 * xmlSchemaPAttrUseErr:
1246 * @ctxt: the schema parser context
1247 * @error: the error code
1248 * @itemDes: the designation of the schema type
1249 * @item: the schema type
1250 * @itemElem: the node of the schema type
1251 * @attr: the invalid schema attribute
1252 * @message: the error message
1253 * @str1: the optional param for the error message
1254 *
1255 * Reports an attribute use error during parsing.
1256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001257static void
1258xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1259 xmlParserErrors error,
1260 xmlChar **itemDes,
1261 xmlSchemaTypePtr item,
1262 xmlNodePtr itemElem,
1263 const xmlSchemaAttributePtr attr,
1264 const char *message,
1265 const xmlChar *str1)
1266{
1267 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1268
1269 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1270 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1271 xmlSchemaGetAttrName(attr));
1272 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1273 msg = xmlStrcat(msg, (const xmlChar *) message);
1274 msg = xmlStrcat(msg, BAD_CAST ".\n");
1275 if ((itemElem == NULL) && (item != NULL))
1276 itemElem = item->node;
1277 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1278 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1279 if (itemDes == NULL)
1280 FREE_AND_NULL(des);
1281 FREE_AND_NULL(strA);
1282 xmlFree(msg);
1283}
1284
William M. Brack2f2a6632004-08-20 23:09:47 +00001285/**
1286 * xmlSchemaPIllegalFacetAtomicErr:
1287 * @ctxt: the schema parser context
1288 * @error: the error code
1289 * @itemDes: the designation of the type
1290 * @item: the schema type
1291 * @baseItem: the base type of type
1292 * @facet: the illegal facet
1293 *
1294 * Reports an illegal facet for atomic simple types.
1295 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001296static void
1297xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1298 xmlParserErrors error,
1299 xmlChar **itemDes,
1300 xmlSchemaTypePtr item,
1301 xmlSchemaTypePtr baseItem,
1302 xmlSchemaFacetPtr facet)
1303{
1304 xmlChar *des = NULL, *strT = NULL;
1305
1306 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1307 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1308 "%s: The facet '%s' is not allowed on types derived from the "
1309 "type %s.\n",
1310 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1311 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1312 NULL, NULL);
1313 if (itemDes == NULL)
1314 FREE_AND_NULL(des);
1315 FREE_AND_NULL(strT);
1316}
1317
William M. Brack2f2a6632004-08-20 23:09:47 +00001318/**
1319 * xmlSchemaPIllegalFacetListUnionErr:
1320 * @ctxt: the schema parser context
1321 * @error: the error code
1322 * @itemDes: the designation of the schema item involved
1323 * @item: the schema item involved
1324 * @facet: the illegal facet
1325 *
1326 * Reports an illegal facet for <list> and <union>.
1327 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001328static void
1329xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1330 xmlParserErrors error,
1331 xmlChar **itemDes,
1332 xmlSchemaTypePtr item,
1333 xmlSchemaFacetPtr facet)
1334{
1335 xmlChar *des = NULL, *strT = NULL;
1336
1337 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1338 xmlSchemaPErr(ctxt, item->node, error,
1339 "%s: The facet '%s' is not allowed.\n",
1340 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1341 if (itemDes == NULL)
1342 FREE_AND_NULL(des);
1343 FREE_AND_NULL(strT);
1344}
1345
1346/**
1347 * xmlSchemaPMutualExclAttrErr:
1348 * @ctxt: the schema validation context
1349 * @error: the error code
1350 * @elemDes: the designation of the parent element node
1351 * @attr: the bad attribute node
1352 * @type: the corresponding type of the attribute node
1353 *
1354 * Reports an illegal attribute.
1355 */
1356static void
1357xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1358 xmlParserErrors error,
1359 xmlChar **ownerDes,
1360 xmlSchemaTypePtr ownerItem,
1361 xmlAttrPtr attr,
1362 const char *name1,
1363 const char *name2)
1364{
1365 xmlChar *des = NULL;
1366
1367 if (ownerDes == NULL)
1368 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1369 else if (*ownerDes == NULL) {
1370 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1371 des = *ownerDes;
1372 } else
1373 des = *ownerDes;
1374 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1375 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1376 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1377 if (ownerDes == NULL)
1378 FREE_AND_NULL(des)
1379}
1380
1381/**
1382 * xmlSchemaPSimpleTypeErr:
1383 * @ctxt: the schema validation context
1384 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001385 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001386 * @ownerDes: the designation of the owner
1387 * @ownerItem: the schema object if existent
1388 * @node: the validated node
1389 * @value: the validated value
1390 *
1391 * Reports a simple type validation error.
1392 * TODO: Should this report the value of an element as well?
1393 */
1394static void
1395xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1396 xmlParserErrors error,
1397 xmlChar **ownerDes,
1398 xmlSchemaTypePtr ownerItem,
1399 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001400 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001401 const char *typeDes,
1402 const xmlChar *value,
1403 const char *message,
1404 const xmlChar *str1,
1405 const xmlChar *str2)
1406{
William M. Brack2f2a6632004-08-20 23:09:47 +00001407 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001408
1409 if (ownerDes == NULL)
1410 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1411 else if (*ownerDes == NULL) {
1412 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1413 des = *ownerDes;
1414 } else
1415 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001416 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001417 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001418 if (message == NULL) {
1419 /*
1420 * Use default messages.
1421 */
1422 if (node->type == XML_ATTRIBUTE_NODE) {
1423 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1424 "%s, attribute '%s' [%s]: The value '%s' is not "
1425 "valid.\n",
1426 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1427 node->name), BAD_CAST typeDes, value, NULL);
1428 } else {
1429 xmlSchemaPErr(ctxt, node, error,
1430 "%s [%s]: The character content is not valid.\n",
1431 BAD_CAST des, BAD_CAST typeDes);
1432 }
1433 } else {
1434 xmlChar *msg;
1435
1436 msg = xmlStrdup(BAD_CAST "%s");
1437 if (node->type == XML_ATTRIBUTE_NODE)
1438 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1439 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1440 msg = xmlStrcat(msg, (const xmlChar *) message);
1441 msg = xmlStrcat(msg, BAD_CAST ".\n");
1442 if (node->type == XML_ATTRIBUTE_NODE) {
1443 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1444 (const char *) msg,
1445 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1446 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1447 } else {
1448 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1449 (const char *) msg,
1450 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1451 }
1452 xmlFree(msg);
1453 }
1454 /* Cleanup. */
1455 FREE_AND_NULL(strA)
1456 FREE_AND_NULL(strT)
1457 if (ownerDes == NULL)
1458 FREE_AND_NULL(des)
1459}
1460
William M. Brack2f2a6632004-08-20 23:09:47 +00001461/**
1462 * xmlSchemaPContentErr:
1463 * @ctxt: the schema parser context
1464 * @error: the error code
1465 * @onwerDes: the designation of the holder of the content
1466 * @ownerItem: the owner item of the holder of the content
1467 * @ownerElem: the node of the holder of the content
1468 * @child: the invalid child node
1469 * @message: the optional error message
1470 * @content: the optional string describing the correct content
1471 *
1472 * Reports an error concerning the content of a schema element.
1473 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001474static void
1475xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1476 xmlParserErrors error,
1477 xmlChar **ownerDes,
1478 xmlSchemaTypePtr ownerItem,
1479 xmlNodePtr ownerElem,
1480 xmlNodePtr child,
1481 const char *message,
1482 const char *content)
1483{
1484 xmlChar *des = NULL;
1485
1486 if (ownerDes == NULL)
1487 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1488 else if (*ownerDes == NULL) {
1489 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1490 des = *ownerDes;
1491 } else
1492 des = *ownerDes;
1493 if (message != NULL)
1494 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1495 "%s: %s.\n",
1496 BAD_CAST des, BAD_CAST message);
1497 else {
1498 if (content != NULL) {
1499 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1500 "%s: The content is not valid. Expected is %s.\n",
1501 BAD_CAST des, BAD_CAST content);
1502 } else {
1503 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1504 "%s: The content is not valid.\n",
1505 BAD_CAST des, NULL);
1506 }
1507 }
1508 if (ownerDes == NULL)
1509 FREE_AND_NULL(des)
1510}
1511
1512/**
1513 * xmlSchemaVIllegalAttrErr:
1514 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001515 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001516 * @attr: the illegal attribute node
1517 *
1518 * Reports an illegal attribute.
1519 */
1520static void
1521xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001522 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001523 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001524{
1525 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001526
1527 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1528 error,
1529 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001530 "%s: The attribute '%s' is not allowed.\n",
1531 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1532 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1533 FREE_AND_NULL(strE)
1534 FREE_AND_NULL(strA)
1535}
1536
William M. Brack2f2a6632004-08-20 23:09:47 +00001537/**
1538 * xmlSchemaVCustomErr:
1539 * @ctxt: the schema validation context
1540 * @error: the error code
1541 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001542 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001543 * @message: the error message
1544 * @str1: the optional param for the message
1545 *
1546 * Reports a validation error.
1547 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001548static void
1549xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1550 xmlParserErrors error,
1551 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001552 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001553 const char *message,
1554 const xmlChar *str1)
1555{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001556 xmlChar *msg = NULL, *str = NULL;
1557
1558 if (node == NULL) {
1559 xmlSchemaVErr(ctxt, NULL,
1560 XML_SCHEMAV_INTERNAL,
1561 "Internal error: xmlSchemaVCustomErr, no node "
1562 "given.\n", NULL, NULL);
1563 return;
1564 }
1565 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1566 if (node->type != XML_DOCUMENT_NODE) {
1567 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1568 if (type != NULL) {
1569 msg = xmlStrcat(msg, BAD_CAST " [");
1570 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1571 msg = xmlStrcat(msg, BAD_CAST "]");
1572 }
1573 msg = xmlStrcat(msg, BAD_CAST ": ");
1574 } else
1575 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001576 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001577 msg = xmlStrcat(msg, BAD_CAST ".\n");
1578 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1579 FREE_AND_NULL(msg)
1580 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001581}
1582
William M. Brack2f2a6632004-08-20 23:09:47 +00001583/**
1584 * xmlSchemaWildcardPCToString:
1585 * @pc: the type of processContents
1586 *
1587 * Returns a string representation of the type of
1588 * processContents.
1589 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001590static const char *
1591xmlSchemaWildcardPCToString(int pc)
1592{
1593 switch (pc) {
1594 case XML_SCHEMAS_ANY_SKIP:
1595 return ("skip");
1596 case XML_SCHEMAS_ANY_LAX:
1597 return ("lax");
1598 case XML_SCHEMAS_ANY_STRICT:
1599 return ("strict");
1600 default:
1601 return ("invalid process contents");
1602 }
1603}
1604
William M. Brack2f2a6632004-08-20 23:09:47 +00001605/**
1606 * xmlSchemaVWildcardErr:
1607 * @ctxt: the schema validation context
1608 * @error: the error code
1609 * @node: the validated node
1610 * @wild: the wildcard used
1611 * @message: the error message
1612 *
1613 * Reports an validation-by-wildcard error.
1614 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001615static void
1616xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1617 xmlParserErrors error,
1618 xmlNodePtr node,
1619 xmlSchemaWildcardPtr wild,
1620 const char *message)
1621{
1622 xmlChar *des = NULL, *msg = NULL;
1623
1624 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1625 msg = xmlStrdup(BAD_CAST "%s, [");
1626 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1627 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1628 msg = xmlStrcat(msg, (const xmlChar *) message);
1629 msg = xmlStrcat(msg, BAD_CAST ".\n");
1630 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1631 FREE_AND_NULL(des);
1632 FREE_AND_NULL(msg);
1633}
1634
1635/**
1636 * xmlSchemaVMissingAttrErr:
1637 * @ctxt: the schema validation context
1638 * @node: the parent element node of the missing attribute node
1639 * @type: the corresponding type of the attribute node
1640 *
1641 * Reports an illegal attribute.
1642 */
1643static void
1644xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1645 xmlNodePtr elem,
1646 xmlSchemaAttributePtr type)
1647{
1648 const xmlChar *name, *uri;
1649 xmlChar *strE = NULL, *strA = NULL;
1650
1651 if (type->ref != NULL) {
1652 name = type->ref;
1653 uri = type->refNs;
1654 } else {
1655 name = type->name;
1656 uri = type->targetNamespace;
1657 }
1658 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001659 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1660 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001661 "%s: The attribute %s is required but missing.\n",
1662 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1663 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1664 FREE_AND_NULL(strE)
1665 FREE_AND_NULL(strA)
1666}
1667
Daniel Veillard4255d502002-04-16 15:50:10 +00001668/************************************************************************
1669 * *
1670 * Allocation functions *
1671 * *
1672 ************************************************************************/
1673
1674/**
1675 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +00001676 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001677 *
1678 * Allocate a new Schema structure.
1679 *
1680 * Returns the newly allocated structure or NULL in case or error
1681 */
1682static xmlSchemaPtr
1683xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1684{
1685 xmlSchemaPtr ret;
1686
1687 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1688 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001689 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001690 return (NULL);
1691 }
1692 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001693 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001694 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001695
1696 return (ret);
1697}
1698
1699/**
1700 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001701 *
1702 * Allocate a new Facet structure.
1703 *
1704 * Returns the newly allocated structure or NULL in case or error
1705 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001706xmlSchemaFacetPtr
1707xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001708{
1709 xmlSchemaFacetPtr ret;
1710
1711 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1712 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001713 return (NULL);
1714 }
1715 memset(ret, 0, sizeof(xmlSchemaFacet));
1716
1717 return (ret);
1718}
1719
1720/**
1721 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001722 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001723 * @node: a node
1724 *
1725 * Allocate a new annotation structure.
1726 *
1727 * Returns the newly allocated structure or NULL in case or error
1728 */
1729static xmlSchemaAnnotPtr
1730xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1731{
1732 xmlSchemaAnnotPtr ret;
1733
1734 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1735 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001736 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001737 return (NULL);
1738 }
1739 memset(ret, 0, sizeof(xmlSchemaAnnot));
1740 ret->content = node;
1741 return (ret);
1742}
1743
1744/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001745 * xmlSchemaFreeAnnot:
1746 * @annot: a schema type structure
1747 *
1748 * Deallocate a annotation structure
1749 */
1750static void
1751xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1752{
1753 if (annot == NULL)
1754 return;
1755 xmlFree(annot);
1756}
1757
1758/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001759 * xmlSchemaFreeImport:
1760 * @import: a schema import structure
1761 *
1762 * Deallocate an import structure
1763 */
1764static void
1765xmlSchemaFreeImport(xmlSchemaImportPtr import)
1766{
1767 if (import == NULL)
1768 return;
1769
1770 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001771 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001772 xmlFree(import);
1773}
1774
1775/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001776 * xmlSchemaFreeInclude:
1777 * @include: a schema include structure
1778 *
1779 * Deallocate an include structure
1780 */
1781static void
1782xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1783{
1784 if (include == NULL)
1785 return;
1786
1787 xmlFreeDoc(include->doc);
1788 xmlFree(include);
1789}
1790
1791/**
1792 * xmlSchemaFreeIncludeList:
1793 * @includes: a schema include list
1794 *
1795 * Deallocate an include structure
1796 */
1797static void
1798xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1799{
1800 xmlSchemaIncludePtr next;
1801
1802 while (includes != NULL) {
1803 next = includes->next;
1804 xmlSchemaFreeInclude(includes);
1805 includes = next;
1806 }
1807}
1808
1809/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001810 * xmlSchemaFreeNotation:
1811 * @schema: a schema notation structure
1812 *
1813 * Deallocate a Schema Notation structure.
1814 */
1815static void
1816xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1817{
1818 if (nota == NULL)
1819 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001820 xmlFree(nota);
1821}
1822
1823/**
1824 * xmlSchemaFreeAttribute:
1825 * @schema: a schema attribute structure
1826 *
1827 * Deallocate a Schema Attribute structure.
1828 */
1829static void
1830xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1831{
1832 if (attr == NULL)
1833 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001834 if (attr->annot != NULL)
1835 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001836 xmlFree(attr);
1837}
1838
1839/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001840 * xmlSchemaFreeWildcardNsSet:
1841 * set: a schema wildcard namespace
1842 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001843 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001844 */
1845static void
1846xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1847{
1848 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001849
Daniel Veillard3646d642004-06-02 19:19:14 +00001850 while (set != NULL) {
1851 next = set->next;
1852 xmlFree(set);
1853 set = next;
1854 }
1855}
1856
1857/**
1858 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001859 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001860 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001861 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001862 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001863void
Daniel Veillard3646d642004-06-02 19:19:14 +00001864xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
1865{
1866 if (wildcard == NULL)
1867 return;
1868 if (wildcard->annot != NULL)
1869 xmlSchemaFreeAnnot(wildcard->annot);
1870 if (wildcard->nsSet != NULL)
1871 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
1872 if (wildcard->negNsSet != NULL)
1873 xmlFree(wildcard->negNsSet);
1874 xmlFree(wildcard);
1875}
1876
1877/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001878 * xmlSchemaFreeAttributeGroup:
1879 * @schema: a schema attribute group structure
1880 *
1881 * Deallocate a Schema Attribute Group structure.
1882 */
1883static void
1884xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
1885{
1886 if (attr == NULL)
1887 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00001888 if (attr->annot != NULL)
1889 xmlSchemaFreeAnnot(attr->annot);
1890 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
1891 (attr->attributeWildcard != NULL))
1892 xmlSchemaFreeWildcard(attr->attributeWildcard);
1893
Daniel Veillard4255d502002-04-16 15:50:10 +00001894 xmlFree(attr);
1895}
1896
1897/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001898 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001899 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00001900 *
1901 * Deallocate a list of schema attribute uses.
1902 */
1903static void
1904xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
1905{
1906 xmlSchemaAttributeLinkPtr next;
1907
1908 while (attrUse != NULL) {
1909 next = attrUse->next;
1910 xmlFree(attrUse);
1911 attrUse = next;
1912 }
1913}
1914
1915/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00001916 * xmlSchemaFreeTypeLinkList:
1917 * @alink: a type link
1918 *
1919 * Deallocate a list of types.
1920 */
1921static void
1922xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
1923{
1924 xmlSchemaTypeLinkPtr next;
1925
1926 while (link != NULL) {
1927 next = link->next;
1928 xmlFree(link);
1929 link = next;
1930 }
1931}
1932
1933/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001934 * xmlSchemaFreeElement:
1935 * @schema: a schema element structure
1936 *
1937 * Deallocate a Schema Element structure.
1938 */
1939static void
1940xmlSchemaFreeElement(xmlSchemaElementPtr elem)
1941{
1942 if (elem == NULL)
1943 return;
Daniel Veillard32370232002-10-16 14:08:14 +00001944 if (elem->annot != NULL)
1945 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001946 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001948 xmlFree(elem);
1949}
1950
1951/**
1952 * xmlSchemaFreeFacet:
1953 * @facet: a schema facet structure
1954 *
1955 * Deallocate a Schema Facet structure.
1956 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001957void
Daniel Veillard4255d502002-04-16 15:50:10 +00001958xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
1959{
1960 if (facet == NULL)
1961 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001962 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001963 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001964 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001965 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00001966 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001967 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001968 xmlFree(facet);
1969}
1970
1971/**
1972 * xmlSchemaFreeType:
1973 * @type: a schema type structure
1974 *
1975 * Deallocate a Schema Type structure.
1976 */
1977void
1978xmlSchemaFreeType(xmlSchemaTypePtr type)
1979{
1980 if (type == NULL)
1981 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001982 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00001983 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001984 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001985 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001986
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001987 facet = type->facets;
1988 while (facet != NULL) {
1989 next = facet->next;
1990 xmlSchemaFreeFacet(facet);
1991 facet = next;
1992 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001993 }
Daniel Veillard3646d642004-06-02 19:19:14 +00001994 if (type->type != XML_SCHEMA_TYPE_BASIC) {
1995 if (type->attributeUses != NULL)
1996 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00001997 /* TODO: There must be a way more simple than this. */
Daniel Veillard3646d642004-06-02 19:19:14 +00001998 if ((type->attributeWildcard != NULL) &&
1999 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
2000 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
2001 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
2002 xmlSchemaFreeWildcard(type->attributeWildcard);
2003 }
2004 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002005 if (type->memberTypes != NULL)
2006 xmlSchemaFreeTypeLinkList(type->memberTypes);
2007 if (type->facetSet != NULL) {
2008 xmlSchemaFacetLinkPtr next, link;
2009
2010 link = type->facetSet;
2011 do {
2012 next = link->next;
2013 xmlFree(link);
2014 link = next;
2015 } while (link != NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00002016 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002017 xmlFree(type);
2018}
2019
2020/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002021 * xmlSchemaFreeTypeList:
2022 * @type: a schema type structure
2023 *
2024 * Deallocate a Schema Type structure.
2025 */
2026static void
2027xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2028{
2029 xmlSchemaTypePtr next;
2030
2031 while (type != NULL) {
2032 next = type->redef;
2033 xmlSchemaFreeType(type);
2034 type = next;
2035 }
2036}
2037
2038/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002039 * xmlSchemaFree:
2040 * @schema: a schema structure
2041 *
2042 * Deallocate a Schema structure.
2043 */
2044void
2045xmlSchemaFree(xmlSchemaPtr schema)
2046{
2047 if (schema == NULL)
2048 return;
2049
Daniel Veillard4255d502002-04-16 15:50:10 +00002050 if (schema->notaDecl != NULL)
2051 xmlHashFree(schema->notaDecl,
2052 (xmlHashDeallocator) xmlSchemaFreeNotation);
2053 if (schema->attrDecl != NULL)
2054 xmlHashFree(schema->attrDecl,
2055 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2056 if (schema->attrgrpDecl != NULL)
2057 xmlHashFree(schema->attrgrpDecl,
2058 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2059 if (schema->elemDecl != NULL)
2060 xmlHashFree(schema->elemDecl,
2061 (xmlHashDeallocator) xmlSchemaFreeElement);
2062 if (schema->typeDecl != NULL)
2063 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002064 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002065 if (schema->groupDecl != NULL)
2066 xmlHashFree(schema->groupDecl,
2067 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002068 if (schema->schemasImports != NULL)
2069 xmlHashFree(schema->schemasImports,
2070 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002071 if (schema->includes != NULL) {
2072 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2073 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002074 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002075 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002076 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002077 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002078 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002079
2080 xmlFree(schema);
2081}
2082
2083/************************************************************************
2084 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002085 * Debug functions *
2086 * *
2087 ************************************************************************/
2088
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002089#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090
Daniel Veillard4255d502002-04-16 15:50:10 +00002091/**
2092 * xmlSchemaElementDump:
2093 * @elem: an element
2094 * @output: the file output
2095 *
2096 * Dump the element
2097 */
2098static void
2099xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002100 const xmlChar * name ATTRIBUTE_UNUSED,
2101 const xmlChar * context ATTRIBUTE_UNUSED,
2102 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002103{
2104 if (elem == NULL)
2105 return;
2106
2107 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002108 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2109 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002110 fprintf(output, ": %s ", elem->name);
2111 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002112 fprintf(output, "namespace '%s' ", namespace);
2113
Daniel Veillard4255d502002-04-16 15:50:10 +00002114 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002115 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002116 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002117 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002118 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002119 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002120 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002121 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002122 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002123 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002124 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002125 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002126 fprintf(output, "\n");
2127 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002128 fprintf(output, " ");
2129 if (elem->minOccurs != 1)
2130 fprintf(output, "min: %d ", elem->minOccurs);
2131 if (elem->maxOccurs >= UNBOUNDED)
2132 fprintf(output, "max: unbounded\n");
2133 else if (elem->maxOccurs != 1)
2134 fprintf(output, "max: %d\n", elem->maxOccurs);
2135 else
2136 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002137 }
2138 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002139 fprintf(output, " type: %s", elem->namedType);
2140 if (elem->namedTypeNs != NULL)
2141 fprintf(output, " ns %s\n", elem->namedTypeNs);
2142 else
2143 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002144 }
2145 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002146 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2147 if (elem->substGroupNs != NULL)
2148 fprintf(output, " ns %s\n", elem->substGroupNs);
2149 else
2150 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002151 }
2152 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002153 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002154}
2155
2156/**
2157 * xmlSchemaAnnotDump:
2158 * @output: the file output
2159 * @annot: a annotation
2160 *
2161 * Dump the annotation
2162 */
2163static void
2164xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2165{
2166 xmlChar *content;
2167
2168 if (annot == NULL)
2169 return;
2170
2171 content = xmlNodeGetContent(annot->content);
2172 if (content != NULL) {
2173 fprintf(output, " Annot: %s\n", content);
2174 xmlFree(content);
2175 } else
2176 fprintf(output, " Annot: empty\n");
2177}
2178
2179/**
2180 * xmlSchemaTypeDump:
2181 * @output: the file output
2182 * @type: a type structure
2183 *
2184 * Dump a SchemaType structure
2185 */
2186static void
2187xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2188{
2189 if (type == NULL) {
2190 fprintf(output, "Type: NULL\n");
2191 return;
2192 }
2193 fprintf(output, "Type: ");
2194 if (type->name != NULL)
2195 fprintf(output, "%s, ", type->name);
2196 else
2197 fprintf(output, "no name");
2198 switch (type->type) {
2199 case XML_SCHEMA_TYPE_BASIC:
2200 fprintf(output, "basic ");
2201 break;
2202 case XML_SCHEMA_TYPE_SIMPLE:
2203 fprintf(output, "simple ");
2204 break;
2205 case XML_SCHEMA_TYPE_COMPLEX:
2206 fprintf(output, "complex ");
2207 break;
2208 case XML_SCHEMA_TYPE_SEQUENCE:
2209 fprintf(output, "sequence ");
2210 break;
2211 case XML_SCHEMA_TYPE_CHOICE:
2212 fprintf(output, "choice ");
2213 break;
2214 case XML_SCHEMA_TYPE_ALL:
2215 fprintf(output, "all ");
2216 break;
2217 case XML_SCHEMA_TYPE_UR:
2218 fprintf(output, "ur ");
2219 break;
2220 case XML_SCHEMA_TYPE_RESTRICTION:
2221 fprintf(output, "restriction ");
2222 break;
2223 case XML_SCHEMA_TYPE_EXTENSION:
2224 fprintf(output, "extension ");
2225 break;
2226 default:
2227 fprintf(output, "unknowntype%d ", type->type);
2228 break;
2229 }
2230 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002231 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002232 }
2233 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002234 case XML_SCHEMA_CONTENT_UNKNOWN:
2235 fprintf(output, "unknown ");
2236 break;
2237 case XML_SCHEMA_CONTENT_EMPTY:
2238 fprintf(output, "empty ");
2239 break;
2240 case XML_SCHEMA_CONTENT_ELEMENTS:
2241 fprintf(output, "element ");
2242 break;
2243 case XML_SCHEMA_CONTENT_MIXED:
2244 fprintf(output, "mixed ");
2245 break;
2246 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002247 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 break;
2249 case XML_SCHEMA_CONTENT_BASIC:
2250 fprintf(output, "basic ");
2251 break;
2252 case XML_SCHEMA_CONTENT_SIMPLE:
2253 fprintf(output, "simple ");
2254 break;
2255 case XML_SCHEMA_CONTENT_ANY:
2256 fprintf(output, "any ");
2257 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002258 }
2259 fprintf(output, "\n");
2260 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002261 fprintf(output, " ");
2262 if (type->minOccurs != 1)
2263 fprintf(output, "min: %d ", type->minOccurs);
2264 if (type->maxOccurs >= UNBOUNDED)
2265 fprintf(output, "max: unbounded\n");
2266 else if (type->maxOccurs != 1)
2267 fprintf(output, "max: %d\n", type->maxOccurs);
2268 else
2269 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 }
2271 if (type->annot != NULL)
2272 xmlSchemaAnnotDump(output, type->annot);
2273 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002274 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002275
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002276 fprintf(output, " subtypes: ");
2277 while (sub != NULL) {
2278 fprintf(output, "%s ", sub->name);
2279 sub = sub->next;
2280 }
2281 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002282 }
2283
2284}
2285
2286/**
2287 * xmlSchemaDump:
2288 * @output: the file output
2289 * @schema: a schema structure
2290 *
2291 * Dump a Schema structure.
2292 */
2293void
2294xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2295{
2296 if (schema == NULL) {
2297 fprintf(output, "Schemas: NULL\n");
2298 return;
2299 }
2300 fprintf(output, "Schemas: ");
2301 if (schema->name != NULL)
2302 fprintf(output, "%s, ", schema->name);
2303 else
2304 fprintf(output, "no name, ");
2305 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002306 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002307 else
2308 fprintf(output, "no target namespace");
2309 fprintf(output, "\n");
2310 if (schema->annot != NULL)
2311 xmlSchemaAnnotDump(output, schema->annot);
2312
2313 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2314 output);
2315 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002316 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002317}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002318#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002319
2320/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002321 * *
2322 * Utilities *
2323 * *
2324 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002325
Daniel Veillardc0826a72004-08-10 14:17:33 +00002326/**
2327 * xmlSchemaGetPropNode:
2328 * @node: the element node
2329 * @name: the name of the attribute
2330 *
2331 * Seeks an attribute with a name of @name in
2332 * no namespace.
2333 *
2334 * Returns the attribute or NULL if not present.
2335 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002336static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002337xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002338{
2339 xmlAttrPtr prop;
2340
Daniel Veillardc0826a72004-08-10 14:17:33 +00002341 if ((node == NULL) || (name == NULL))
2342 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002343 prop = node->properties;
2344 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002345 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2346 return(prop);
2347 prop = prop->next;
2348 }
2349 return (NULL);
2350}
2351
2352/**
2353 * xmlSchemaGetPropNodeNs:
2354 * @node: the element node
2355 * @uri: the uri
2356 * @name: the name of the attribute
2357 *
2358 * Seeks an attribute with a local name of @name and
2359 * a namespace URI of @uri.
2360 *
2361 * Returns the attribute or NULL if not present.
2362 */
2363static xmlAttrPtr
2364xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2365{
2366 xmlAttrPtr prop;
2367
2368 if ((node == NULL) || (name == NULL))
2369 return(NULL);
2370 prop = node->properties;
2371 while (prop != NULL) {
2372 if ((prop->ns != NULL) &&
2373 xmlStrEqual(prop->name, BAD_CAST name) &&
2374 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002375 return(prop);
2376 prop = prop->next;
2377 }
2378 return (NULL);
2379}
2380
2381static const xmlChar *
2382xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2383{
2384 xmlChar *val;
2385 const xmlChar *ret;
2386
2387 val = xmlNodeGetContent(node);
2388 if (val == NULL)
2389 return(NULL);
2390 ret = xmlDictLookup(ctxt->dict, val, -1);
2391 xmlFree(val);
2392 return(ret);
2393}
2394
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002395/**
2396 * xmlSchemaGetProp:
2397 * @ctxt: the parser context
2398 * @node: the node
2399 * @name: the property name
2400 *
2401 * Read a attribute value and internalize the string
2402 *
2403 * Returns the string or NULL if not present.
2404 */
2405static const xmlChar *
2406xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2407 const char *name)
2408{
2409 xmlChar *val;
2410 const xmlChar *ret;
2411
2412 val = xmlGetProp(node, BAD_CAST name);
2413 if (val == NULL)
2414 return(NULL);
2415 ret = xmlDictLookup(ctxt->dict, val, -1);
2416 xmlFree(val);
2417 return(ret);
2418}
2419
William M. Brack29aa7722004-05-12 00:27:56 +00002420#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002421/**
2422 * xmlSchemaGetNamespace:
2423 * @ctxt: the parser context
2424 * @schema: the schemas containing the declaration
2425 * @node: the node
2426 * @qname: the QName to analyze
2427 *
2428 * Find the namespace name for the given declaration.
2429 *
2430 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00002431 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002432 */
2433static const xmlChar *
2434xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2435 xmlNodePtr node, const xmlChar *qname,
2436 const xmlChar **namespace) {
2437 int len;
2438 const xmlChar *name, *prefix, *def = NULL;
2439 xmlNsPtr ns;
2440
2441 *namespace = NULL;
2442
William M. Bracke7091952004-05-11 15:09:58 +00002443 /* TODO: The following seems to be not correct here:
2444 * 1. The name of a declaration is a NCName, not a QName.
2445 * 2. The attribute "targetNamespace" is allowed for the
2446 * <schema> Element Information Item only.
2447 * 3. One cannot evaluate the target namespace, by the type
2448 * of declaration, since it is dependant on the xxxFormDefault
2449 * of <schema> and the form attribute of an <element> or <attribute>.
2450 */
2451
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002452 if (xmlStrEqual(node->name, BAD_CAST "element") ||
2453 xmlStrEqual(node->name, BAD_CAST "attribute") ||
2454 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
2455 xmlStrEqual(node->name, BAD_CAST "complexType")) {
2456 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
2457 }
2458
William M. Bracke7091952004-05-11 15:09:58 +00002459
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002460 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
2461 name = xmlSplitQName3(qname, &len);
2462 if (name == NULL) {
2463 if (def == NULL) {
2464 if (xmlStrEqual(node->name, BAD_CAST "element")) {
2465 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
2466 *namespace = schema->targetNamespace;
2467 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
2468 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
2469 *namespace = schema->targetNamespace;
2470 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
2471 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
2472 *namespace = schema->targetNamespace;
2473 }
2474 } else {
2475 *namespace = def;
2476 }
2477 return(qname);
2478 }
William M. Bracke7091952004-05-11 15:09:58 +00002479
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002480 name = xmlDictLookup(ctxt->dict, name, -1);
2481 prefix = xmlDictLookup(ctxt->dict, qname, len);
2482 if (def != NULL) {
2483 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
2484 "%s: presence of both prefix %s and targetNamespace\n",
2485 node->name, prefix);
2486 }
2487 ns = xmlSearchNs(node->doc, node, prefix);
2488 if (ns == NULL) {
2489 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002490 "%s: The QName prefix %s is undefined\n",
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002491 node->name, prefix);
2492 return(name);
2493 }
2494 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2495 return(name);
2496}
William M. Brack29aa7722004-05-12 00:27:56 +00002497#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002498
2499/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002500 * *
2501 * Parsing functions *
2502 * *
2503 ************************************************************************/
2504
2505/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002506 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002507 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002508 * @name: the element name
2509 * @ns: the element namespace
2510 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002511 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002512 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002513 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002514 */
2515static xmlSchemaElementPtr
2516xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002517 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002518{
2519 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002520
2521 if ((name == NULL) || (schema == NULL))
2522 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002523
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002524 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002525 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002526 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002527 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002528 } else
2529 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002530 /*
2531 * This one was removed, since top level element declarations have
2532 * the target namespace specified in targetNamespace of the <schema>
2533 * information element, even if elementFormDefault is "unqualified".
2534 */
2535
2536 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002537 if (xmlStrEqual(namespace, schema->targetNamespace))
2538 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2539 else
2540 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002541 if ((ret != NULL) &&
2542 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002543 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002544 }
William M. Bracke7091952004-05-11 15:09:58 +00002545 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002546
William M. Brack2f2a6632004-08-20 23:09:47 +00002547 /*
2548 * Removed since imported components will be hold by the main schema only.
2549 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002550 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002551 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002552 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002553 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002554 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002555 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002556 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2557 return (ret);
2558 } else
2559 ret = NULL;
2560 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002561 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002562#ifdef DEBUG
2563 if (ret == NULL) {
2564 if (namespace == NULL)
2565 fprintf(stderr, "Unable to lookup type %s", name);
2566 else
2567 fprintf(stderr, "Unable to lookup type %s:%s", name,
2568 namespace);
2569 }
2570#endif
2571 return (ret);
2572}
2573
2574/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002575 * xmlSchemaGetType:
2576 * @schema: the schemas context
2577 * @name: the type name
2578 * @ns: the type namespace
2579 *
2580 * Lookup a type in the schemas or the predefined types
2581 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002582 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002583 */
2584static xmlSchemaTypePtr
2585xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002586 const xmlChar * namespace)
2587{
Daniel Veillard4255d502002-04-16 15:50:10 +00002588 xmlSchemaTypePtr ret;
2589
2590 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002591 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002592 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002593 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002594 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002595 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002596 }
2597 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002598 if (ret != NULL)
2599 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002600 /*
2601 * Removed, since the imported components will be grafted on the
2602 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002603 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002604 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002605 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002606 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002607 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002608 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002609 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2610 return (ret);
2611 } else
2612 ret = NULL;
2613 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002614 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002615#ifdef DEBUG
2616 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002617 if (namespace == NULL)
2618 fprintf(stderr, "Unable to lookup type %s", name);
2619 else
2620 fprintf(stderr, "Unable to lookup type %s:%s", name,
2621 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 }
2623#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002624 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002625}
2626
Daniel Veillard3646d642004-06-02 19:19:14 +00002627/**
2628 * xmlSchemaGetAttribute:
2629 * @schema: the context of the schema
2630 * @name: the name of the attribute
2631 * @ns: the target namespace of the attribute
2632 *
2633 * Lookup a an attribute in the schema or imported schemas
2634 *
2635 * Returns the attribute declaration or NULL if not found.
2636 */
2637static xmlSchemaAttributePtr
2638xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2639 const xmlChar * namespace)
2640{
2641 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002642
2643 if ((name == NULL) || (schema == NULL))
2644 return (NULL);
2645
2646
2647 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2648 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2649 return (ret);
2650 else
2651 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002652 /*
2653 * Removed, since imported components will be hold by the main schema only.
2654 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002655 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002656 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002657 else
2658 import = xmlHashLookup(schema->schemasImports, namespace);
2659 if (import != NULL) {
2660 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2661 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2662 return (ret);
2663 } else
2664 ret = NULL;
2665 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002666 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002667#ifdef DEBUG
2668 if (ret == NULL) {
2669 if (namespace == NULL)
2670 fprintf(stderr, "Unable to lookup attribute %s", name);
2671 else
2672 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2673 namespace);
2674 }
2675#endif
2676 return (ret);
2677}
2678
2679/**
2680 * xmlSchemaGetAttributeGroup:
2681 * @schema: the context of the schema
2682 * @name: the name of the attribute group
2683 * @ns: the target namespace of the attribute group
2684 *
2685 * Lookup a an attribute group in the schema or imported schemas
2686 *
2687 * Returns the attribute group definition or NULL if not found.
2688 */
2689static xmlSchemaAttributeGroupPtr
2690xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2691 const xmlChar * namespace)
2692{
2693 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002694
2695 if ((name == NULL) || (schema == NULL))
2696 return (NULL);
2697
2698
2699 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2700 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2701 return (ret);
2702 else
2703 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002704 /*
2705 * Removed since imported components will be hold by the main schema only.
2706 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002707 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002708 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002709 else
2710 import = xmlHashLookup(schema->schemasImports, namespace);
2711 if (import != NULL) {
2712 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2713 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2714 return (ret);
2715 else
2716 ret = NULL;
2717 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002718 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002719#ifdef DEBUG
2720 if (ret == NULL) {
2721 if (namespace == NULL)
2722 fprintf(stderr, "Unable to lookup attribute group %s", name);
2723 else
2724 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2725 namespace);
2726 }
2727#endif
2728 return (ret);
2729}
2730
2731/**
2732 * xmlSchemaGetGroup:
2733 * @schema: the context of the schema
2734 * @name: the name of the group
2735 * @ns: the target namespace of the group
2736 *
2737 * Lookup a group in the schema or imported schemas
2738 *
2739 * Returns the group definition or NULL if not found.
2740 */
2741static xmlSchemaTypePtr
2742xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2743 const xmlChar * namespace)
2744{
2745 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002746
2747 if ((name == NULL) || (schema == NULL))
2748 return (NULL);
2749
2750
2751 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2752 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2753 return (ret);
2754 else
2755 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002756 /*
2757 * Removed since imported components will be hold by the main schema only.
2758 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002759 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002760 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002761 else
2762 import = xmlHashLookup(schema->schemasImports, namespace);
2763 if (import != NULL) {
2764 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2765 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2766 return (ret);
2767 else
2768 ret = NULL;
2769 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002770 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002771#ifdef DEBUG
2772 if (ret == NULL) {
2773 if (namespace == NULL)
2774 fprintf(stderr, "Unable to lookup group %s", name);
2775 else
2776 fprintf(stderr, "Unable to lookup group %s:%s", name,
2777 namespace);
2778 }
2779#endif
2780 return (ret);
2781}
2782
Daniel Veillard4255d502002-04-16 15:50:10 +00002783/************************************************************************
2784 * *
2785 * Parsing functions *
2786 * *
2787 ************************************************************************/
2788
2789#define IS_BLANK_NODE(n) \
2790 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2791
2792/**
2793 * xmlSchemaIsBlank:
2794 * @str: a string
2795 *
2796 * Check if a string is ignorable
2797 *
2798 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2799 */
2800static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002801xmlSchemaIsBlank(xmlChar * str)
2802{
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002804 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002805 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002806 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002807 return (0);
2808 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002810 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002811}
2812
2813/**
2814 * xmlSchemaAddNotation:
2815 * @ctxt: a schema validation context
2816 * @schema: the schema being built
2817 * @name: the item name
2818 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002819 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002820 * *WARNING* this interface is highly subject to change
2821 *
2822 * Returns the new struture or NULL in case of error
2823 */
2824static xmlSchemaNotationPtr
2825xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002826 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002827{
2828 xmlSchemaNotationPtr ret = NULL;
2829 int val;
2830
2831 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2832 return (NULL);
2833
2834 if (schema->notaDecl == NULL)
2835 schema->notaDecl = xmlHashCreate(10);
2836 if (schema->notaDecl == NULL)
2837 return (NULL);
2838
2839 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2840 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002841 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002842 return (NULL);
2843 }
2844 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002845 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002846 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2847 ret);
2848 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002849 /*
2850 * TODO: This should never happen, since a unique name will be computed.
2851 * If it fails, then an other internal error must have occured.
2852 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002853 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2854 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002856 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002857 xmlFree(ret);
2858 return (NULL);
2859 }
2860 return (ret);
2861}
2862
2863
2864/**
2865 * xmlSchemaAddAttribute:
2866 * @ctxt: a schema validation context
2867 * @schema: the schema being built
2868 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002869 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 *
2871 * Add an XML schema Attrribute declaration
2872 * *WARNING* this interface is highly subject to change
2873 *
2874 * Returns the new struture or NULL in case of error
2875 */
2876static xmlSchemaAttributePtr
2877xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002878 const xmlChar * name, const xmlChar * namespace,
2879 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002880{
2881 xmlSchemaAttributePtr ret = NULL;
2882 int val;
2883
2884 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2885 return (NULL);
2886
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002887#ifdef DEBUG
2888 fprintf(stderr, "Adding attribute %s\n", name);
2889 if (namespace != NULL)
2890 fprintf(stderr, " target namespace %s\n", namespace);
2891#endif
2892
Daniel Veillard4255d502002-04-16 15:50:10 +00002893 if (schema->attrDecl == NULL)
2894 schema->attrDecl = xmlHashCreate(10);
2895 if (schema->attrDecl == NULL)
2896 return (NULL);
2897
2898 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
2899 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002900 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002901 return (NULL);
2902 }
2903 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002904 ret->name = xmlDictLookup(ctxt->dict, name, -1);
2905 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002906 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002907 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002908 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00002909 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002910 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00002911 NULL, NULL, node,
2912 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002913 xmlFree(ret);
2914 return (NULL);
2915 }
2916 return (ret);
2917}
2918
2919/**
2920 * xmlSchemaAddAttributeGroup:
2921 * @ctxt: a schema validation context
2922 * @schema: the schema being built
2923 * @name: the item name
2924 *
2925 * Add an XML schema Attrribute Group declaration
2926 *
2927 * Returns the new struture or NULL in case of error
2928 */
2929static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002930xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002931 xmlSchemaPtr schema, const xmlChar * name,
2932 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002933{
2934 xmlSchemaAttributeGroupPtr ret = NULL;
2935 int val;
2936
2937 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2938 return (NULL);
2939
2940 if (schema->attrgrpDecl == NULL)
2941 schema->attrgrpDecl = xmlHashCreate(10);
2942 if (schema->attrgrpDecl == NULL)
2943 return (NULL);
2944
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002945 ret =
2946 (xmlSchemaAttributeGroupPtr)
2947 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00002948 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002949 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002950 return (NULL);
2951 }
2952 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002953 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002954 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002955 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002956 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00002957 xmlSchemaPCustomErr(ctxt,
2958 XML_SCHEMAP_REDEFINED_ATTRGROUP,
2959 NULL, NULL, node,
2960 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002961 xmlFree(ret);
2962 return (NULL);
2963 }
2964 return (ret);
2965}
2966
2967/**
2968 * xmlSchemaAddElement:
2969 * @ctxt: a schema validation context
2970 * @schema: the schema being built
2971 * @name: the type name
2972 * @namespace: the type namespace
2973 *
2974 * Add an XML schema Element declaration
2975 * *WARNING* this interface is highly subject to change
2976 *
2977 * Returns the new struture or NULL in case of error
2978 */
2979static xmlSchemaElementPtr
2980xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002981 const xmlChar * name, const xmlChar * namespace,
2982 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002983{
2984 xmlSchemaElementPtr ret = NULL;
2985 int val;
2986
2987 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2988 return (NULL);
2989
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002990#ifdef DEBUG
2991 fprintf(stderr, "Adding element %s\n", name);
2992 if (namespace != NULL)
2993 fprintf(stderr, " target namespace %s\n", namespace);
2994#endif
2995
Daniel Veillard4255d502002-04-16 15:50:10 +00002996 if (schema->elemDecl == NULL)
2997 schema->elemDecl = xmlHashCreate(10);
2998 if (schema->elemDecl == NULL)
2999 return (NULL);
3000
3001 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3002 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003003 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003004 return (NULL);
3005 }
3006 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003007 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3008 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003009 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003010 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003011 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003012 if (topLevel) {
3013 xmlSchemaPCustomErr(ctxt,
3014 XML_SCHEMAP_REDEFINED_ELEMENT,
3015 NULL, NULL, node,
3016 "A global element declaration with the name '%s' does "
3017 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003018 xmlFree(ret);
3019 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003020 } else {
3021 char buf[30];
3022
3023 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3024 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3025 namespace, ret);
3026 if (val != 0) {
3027 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003028 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003029 NULL, NULL, node,
3030 "Internal error: xmlSchemaAddElement, "
3031 "a dublicate element declaration with the name '%s' "
3032 "could not be added to the hash.", name);
3033 xmlFree(ret);
3034 return (NULL);
3035 }
3036 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003037
Daniel Veillard4255d502002-04-16 15:50:10 +00003038 }
3039 return (ret);
3040}
3041
3042/**
3043 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003044 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003045 * @schema: the schema being built
3046 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003047 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003048 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003049 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 * *WARNING* this interface is highly subject to change
3051 *
3052 * Returns the new struture or NULL in case of error
3053 */
3054static xmlSchemaTypePtr
3055xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003056 const xmlChar * name, const xmlChar * namespace,
3057 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003058{
3059 xmlSchemaTypePtr ret = NULL;
3060 int val;
3061
3062 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3063 return (NULL);
3064
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003065#ifdef DEBUG
3066 fprintf(stderr, "Adding type %s\n", name);
3067 if (namespace != NULL)
3068 fprintf(stderr, " target namespace %s\n", namespace);
3069#endif
3070
Daniel Veillard4255d502002-04-16 15:50:10 +00003071 if (schema->typeDecl == NULL)
3072 schema->typeDecl = xmlHashCreate(10);
3073 if (schema->typeDecl == NULL)
3074 return (NULL);
3075
3076 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3077 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003078 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 return (NULL);
3080 }
3081 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003082 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003083 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003084 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003085 if (val != 0) {
3086 if (ctxt->includes == 0) {
3087 xmlSchemaPCustomErr(ctxt,
3088 XML_SCHEMAP_REDEFINED_TYPE,
3089 NULL, NULL, node,
3090 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003091 xmlFree(ret);
3092 return (NULL);
3093 } else {
3094 xmlSchemaTypePtr prev;
3095
3096 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3097 if (prev == NULL) {
3098 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003099 XML_ERR_INTERNAL_ERROR,
3100 "Internal error: xmlSchemaAddType, on type "
3101 "'%s'.\n",
3102 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003103 xmlFree(ret);
3104 return (NULL);
3105 }
3106 ret->redef = prev->redef;
3107 prev->redef = ret;
3108 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003109 }
3110 ret->minOccurs = 1;
3111 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003112 ret->attributeUses = NULL;
3113 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003114
3115 return (ret);
3116}
3117
3118/**
3119 * xmlSchemaAddGroup:
3120 * @ctxt: a schema validation context
3121 * @schema: the schema being built
3122 * @name: the group name
3123 *
3124 * Add an XML schema Group definition
3125 *
3126 * Returns the new struture or NULL in case of error
3127 */
3128static xmlSchemaTypePtr
3129xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003130 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003131{
3132 xmlSchemaTypePtr ret = NULL;
3133 int val;
3134
3135 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3136 return (NULL);
3137
3138 if (schema->groupDecl == NULL)
3139 schema->groupDecl = xmlHashCreate(10);
3140 if (schema->groupDecl == NULL)
3141 return (NULL);
3142
3143 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3144 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003145 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003146 return (NULL);
3147 }
3148 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003149 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003150 val =
3151 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3152 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003153 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003154 xmlSchemaPCustomErr(ctxt,
3155 XML_SCHEMAP_REDEFINED_GROUP,
3156 NULL, NULL, node,
3157 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 xmlFree(ret);
3159 return (NULL);
3160 }
3161 ret->minOccurs = 1;
3162 ret->maxOccurs = 1;
3163
3164 return (ret);
3165}
3166
Daniel Veillard3646d642004-06-02 19:19:14 +00003167/**
3168 * xmlSchemaNewWildcardNs:
3169 * @ctxt: a schema validation context
3170 *
3171 * Creates a new wildcard namespace constraint.
3172 *
3173 * Returns the new struture or NULL in case of error
3174 */
3175static xmlSchemaWildcardNsPtr
3176xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3177{
3178 xmlSchemaWildcardNsPtr ret;
3179
3180 ret = (xmlSchemaWildcardNsPtr)
3181 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3182 if (ret == NULL) {
3183 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3184 return (NULL);
3185 }
3186 ret->value = NULL;
3187 ret->next = NULL;
3188 return (ret);
3189}
3190
3191/**
3192 * xmlSchemaAddWildcard:
3193 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003194 * Adds a wildcard. It corresponds to a
3195 * xsd:anyAttribute and is used as storage for namespace
3196 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003197 *
3198 * Returns the new struture or NULL in case of error
3199 */
3200static xmlSchemaWildcardPtr
3201xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3202{
3203 xmlSchemaWildcardPtr ret = NULL;
3204
3205 if (ctxt == NULL)
3206 return (NULL);
3207
3208 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3209 if (ret == NULL) {
3210 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3211 return (NULL);
3212 }
3213 memset(ret, 0, sizeof(xmlSchemaWildcard));
3214 ret->minOccurs = 1;
3215 ret->maxOccurs = 1;
3216
3217 return (ret);
3218}
3219
Daniel Veillard4255d502002-04-16 15:50:10 +00003220/************************************************************************
3221 * *
3222 * Utilities for parsing *
3223 * *
3224 ************************************************************************/
3225
3226/**
3227 * xmlGetQNameProp:
3228 * @ctxt: a schema validation context
3229 * @node: a subtree containing XML Schema informations
3230 * @name: the attribute name
3231 * @namespace: the result namespace if any
3232 *
3233 * Extract a QName Attribute value
3234 *
3235 * Returns the NCName or NULL if not found, and also update @namespace
3236 * with the namespace URI
3237 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003238static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003239xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003240 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003241{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003242 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003244 const xmlChar *ret, *prefix;
3245 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00003246
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003247 *namespace = NULL;
3248 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003249 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003250 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003251
Daniel Veillardba0153a2004-04-01 10:42:31 +00003252 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003253 ns = xmlSearchNs(node->doc, node, 0);
3254 if (ns) {
3255 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3256 return (val);
3257 }
3258 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003259 ret = xmlSplitQName3(val, &len);
3260 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003261 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003262 }
3263 ret = xmlDictLookup(ctxt->dict, ret, -1);
3264 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003265
3266 ns = xmlSearchNs(node->doc, node, prefix);
3267 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003269 "Attribute '%s': The prefix '%s' of the QName "
3270 "'%s' has no corresponding namespace declaration is scope.\n",
3271 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00003272 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003273 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003274 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003275 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003276}
3277
3278/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003279 * xmlSchemaPValAttrNodeQNameValue:
3280 * @ctxt: a schema parser context
3281 * @schema: the schema context
3282 * @ownerDes: the designation of the parent element
3283 * @ownerItem: the parent as a schema object
3284 * @value: the QName value
3285 * @local: the resulting local part if found, the attribute value otherwise
3286 * @uri: the resulting namespace URI if found
3287 *
3288 * Extracts the local name and the URI of a QName value and validates it.
3289 * This one is intended to be used on attribute values that
3290 * should resolve to schema components.
3291 *
3292 * Returns 0, in case the QName is valid, a positive error code
3293 * if not valid and -1 if an internal error occurs.
3294 */
3295static int
3296xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3297 xmlSchemaPtr schema,
3298 xmlChar **ownerDes,
3299 xmlSchemaTypePtr ownerItem,
3300 xmlAttrPtr attr,
3301 const xmlChar *value,
3302 const xmlChar **uri,
3303 const xmlChar **prefix,
3304 const xmlChar **local)
3305{
3306 const xmlChar *pref;
3307 xmlNsPtr ns;
3308 int len, ret;
3309
3310 *uri = NULL;
3311 *local = NULL;
3312 if (prefix != 0)
3313 *prefix = NULL;
3314 ret = xmlValidateQName(value, 1);
3315 if (ret > 0) {
3316 xmlSchemaPSimpleTypeErr(ctxt,
3317 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3318 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003319 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3320 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003321 NULL, NULL, NULL);
3322 *local = value;
3323 return (ctxt->err);
3324 } else if (ret < 0)
3325 return (-1);
3326
3327 if (!strchr((char *) value, ':')) {
3328 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3329 if (ns)
3330 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3331 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3332 /*
3333 * This one takes care of included schemas with no
3334 * target namespace.
3335 */
3336 *uri = schema->targetNamespace;
3337 }
3338 *local = value;
3339 return (0);
3340 }
3341 /*
3342 * At this point xmlSplitQName3 has to return a local name.
3343 */
3344 *local = xmlSplitQName3(value, &len);
3345 *local = xmlDictLookup(ctxt->dict, *local, -1);
3346 pref = xmlDictLookup(ctxt->dict, value, len);
3347 if (prefix != 0)
3348 *prefix = pref;
3349 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3350 if (ns == NULL) {
3351 xmlSchemaPSimpleTypeErr(ctxt,
3352 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3353 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003354 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003355 "The prefix '%s' of the value '%s' is not declared.\n",
3356 pref, value);
3357 return (ctxt->err);
3358 } else {
3359 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3360 }
3361 return (0);
3362}
3363
3364/**
3365 * xmlSchemaPValAttrNodeQName:
3366 * @ctxt: a schema parser context
3367 * @schema: the schema context
3368 * @ownerDes: the designation of the owner element
3369 * @ownerItem: the owner as a schema object
3370 * @attr: the attribute node
3371 * @local: the resulting local part if found, the attribute value otherwise
3372 * @uri: the resulting namespace URI if found
3373 *
3374 * Extracts and validates the QName of an attribute value.
3375 * This one is intended to be used on attribute values that
3376 * should resolve to schema components.
3377 *
3378 * Returns 0, in case the QName is valid, a positive error code
3379 * if not valid and -1 if an internal error occurs.
3380 */
3381static int
3382xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3383 xmlSchemaPtr schema,
3384 xmlChar **ownerDes,
3385 xmlSchemaTypePtr ownerItem,
3386 xmlAttrPtr attr,
3387 const xmlChar **uri,
3388 const xmlChar **prefix,
3389 const xmlChar **local)
3390{
3391 const xmlChar *value;
3392
3393 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3394 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3395 ownerDes, ownerItem, attr, value, uri, prefix, local));
3396}
3397
3398/**
3399 * xmlSchemaPValAttrQName:
3400 * @ctxt: a schema parser context
3401 * @schema: the schema context
3402 * @ownerDes: the designation of the parent element
3403 * @ownerItem: the owner as a schema object
3404 * @ownerElem: the parent node of the attribute
3405 * @name: the name of the attribute
3406 * @local: the resulting local part if found, the attribute value otherwise
3407 * @uri: the resulting namespace URI if found
3408 *
3409 * Extracts and validates the QName of an attribute value.
3410 *
3411 * Returns 0, in case the QName is valid, a positive error code
3412 * if not valid and -1 if an internal error occurs.
3413 */
3414static int
3415xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3416 xmlSchemaPtr schema,
3417 xmlChar **ownerDes,
3418 xmlSchemaTypePtr ownerItem,
3419 xmlNodePtr ownerElem,
3420 const char *name,
3421 const xmlChar **uri,
3422 const xmlChar **prefix,
3423 const xmlChar **local)
3424{
3425 xmlAttrPtr attr;
3426
3427 attr = xmlSchemaGetPropNode(ownerElem, name);
3428 if (attr == NULL) {
3429 *local = NULL;
3430 *uri = NULL;
3431 return (0);
3432 }
3433 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3434 ownerDes, ownerItem, attr, uri, prefix, local));
3435}
3436
3437/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 * xmlGetMaxOccurs:
3439 * @ctxt: a schema validation context
3440 * @node: a subtree containing XML Schema informations
3441 *
3442 * Get the maxOccurs property
3443 *
3444 * Returns the default if not found, or the value
3445 */
3446static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003447xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3448 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003449{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003450 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003451 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003452 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003453
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003454 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3455 if (attr == NULL)
3456 return (def);
3457 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003458
3459 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003460 if (max != UNBOUNDED) {
3461 xmlSchemaPSimpleTypeErr(ctxt,
3462 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3463 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3464 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3465 val, NULL, NULL, NULL);
3466 return (def);
3467 } else
3468 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 }
3470
3471 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003472 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003473 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003474 if (*cur == 0) {
3475 xmlSchemaPSimpleTypeErr(ctxt,
3476 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3477 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3478 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3479 val, NULL, NULL, NULL);
3480 return (def);
3481 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003482 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003483 ret = ret * 10 + (*cur - '0');
3484 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003485 }
William M. Brack76e95df2003-10-18 16:20:14 +00003486 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003487 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003488 /*
3489 * TODO: Restrict the maximal value to Integer.
3490 */
3491 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3492 xmlSchemaPSimpleTypeErr(ctxt,
3493 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3494 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3495 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3496 val, NULL, NULL, NULL);
3497 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003500}
3501
3502/**
3503 * xmlGetMinOccurs:
3504 * @ctxt: a schema validation context
3505 * @node: a subtree containing XML Schema informations
3506 *
3507 * Get the minOccurs property
3508 *
3509 * Returns the default if not found, or the value
3510 */
3511static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003512xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3513 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003514{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003515 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003516 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003517 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003518
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003519 attr = xmlSchemaGetPropNode(node, "minOccurs");
3520 if (attr == NULL)
3521 return (def);
3522 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003523 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003524 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003525 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003526 if (*cur == 0) {
3527 xmlSchemaPSimpleTypeErr(ctxt,
3528 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3529 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3530 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3531 val, NULL, NULL, NULL);
3532 return (def);
3533 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003534 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003535 ret = ret * 10 + (*cur - '0');
3536 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003537 }
William M. Brack76e95df2003-10-18 16:20:14 +00003538 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003539 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003540 /*
3541 * TODO: Restrict the maximal value to Integer.
3542 */
3543 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3544 xmlSchemaPSimpleTypeErr(ctxt,
3545 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3546 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3547 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3548 val, NULL, NULL, NULL);
3549 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003550 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003551 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003552}
3553
3554/**
3555 * xmlGetBooleanProp:
3556 * @ctxt: a schema validation context
3557 * @node: a subtree containing XML Schema informations
3558 * @name: the attribute name
3559 * @def: the default value
3560 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003561 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 *
3563 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003564 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003565 */
3566static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003567xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3568 xmlChar **ownerDes,
3569 xmlSchemaTypePtr ownerItem,
3570 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003571 const char *name, int def)
3572{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003573 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003574
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003575 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003576 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003577 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003578 /*
3579 * 3.2.2.1 Lexical representation
3580 * An instance of a datatype that is defined as ·boolean·
3581 * can have the following legal literals {true, false, 1, 0}.
3582 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003583 if (xmlStrEqual(val, BAD_CAST "true"))
3584 def = 1;
3585 else if (xmlStrEqual(val, BAD_CAST "false"))
3586 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003587 else if (xmlStrEqual(val, BAD_CAST "1"))
3588 def = 1;
3589 else if (xmlStrEqual(val, BAD_CAST "0"))
3590 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003591 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003592 xmlSchemaPSimpleTypeErr(ctxt,
3593 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003594 ownerDes, ownerItem, node,
3595 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3596 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003597 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003598 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003599}
3600
3601/************************************************************************
3602 * *
3603 * Shema extraction from an Infoset *
3604 * *
3605 ************************************************************************/
3606static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3607 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003608 xmlNodePtr node,
3609 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3611 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003613 xmlNodePtr node,
3614 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003615static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3616 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003618 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003619static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3620 xmlSchemaPtr schema,
3621 xmlNodePtr node);
3622static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3623 xmlSchemaPtr schema,
3624 xmlNodePtr node);
3625static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3626 ctxt,
3627 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003628 xmlNodePtr node,
3629 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003630static xmlSchemaAttributeGroupPtr
3631xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003632 xmlSchemaPtr schema, xmlNodePtr node,
3633 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003634static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3635 xmlSchemaPtr schema,
3636 xmlNodePtr node);
3637static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3638 xmlSchemaPtr schema,
3639 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003640static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3642 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003643
3644/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003645 * xmlSchemaPValAttrNode:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003646 *
3647 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003648 * @ownerDes: the designation of the parent element
3649 * @ownerItem: the schema object owner if existent
3650 * @attr: the schema attribute node being validated
3651 * @value: the value
3652 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003653 *
3654 * Validates a value against the given built-in type.
3655 * This one is intended to be used internally for validation
3656 * of schema attribute values during parsing of the schema.
3657 *
3658 * Returns 0 if the value is valid, a positive error code
3659 * number otherwise and -1 in case of an internal or API error.
3660 */
3661static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003662xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3663 xmlChar **ownerDes,
3664 xmlSchemaTypePtr ownerItem,
3665 xmlAttrPtr attr,
3666 const xmlChar *value,
3667 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003668{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003669
Daniel Veillardc0826a72004-08-10 14:17:33 +00003670 int ret = 0;
3671
3672 /*
3673 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3674 * one is really meant to be used internally, so better not.
3675 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003676 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003677 return (-1);
3678 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3679 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003680 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003681 "Internal error: xmlSchemaPvalueAttrNode, the given "
3682 "type '%s' is not a built-in type.\n",
3683 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003684 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003685 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003686 switch (type->builtInType) {
3687 case XML_SCHEMAS_NCNAME:
3688 ret = xmlValidateNCName(value, 1);
3689 break;
3690 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003691 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003692 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003693 "Internal error: xmlSchemaPvalueAttrNode, use "
3694 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3695 "for extracting QName valueues instead.\n",
3696 NULL, NULL);
3697 return (-1);
3698 case XML_SCHEMAS_ANYURI:
3699 if (value != NULL) {
3700 xmlURIPtr uri = xmlParseURI((const char *) value);
3701 if (uri == NULL)
3702 ret = 1;
3703 else
3704 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003705 }
3706 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003707 case XML_SCHEMAS_TOKEN: {
3708 const xmlChar *cur = value;
3709
3710 if (IS_BLANK_CH(*cur)) {
3711 ret = 1;
3712 } else while (*cur != 0) {
3713 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3714 ret = 1;
3715 break;
3716 } else if (*cur == ' ') {
3717 cur++;
3718 if ((*cur == 0) || (*cur == ' ')) {
3719 ret = 1;
3720 break;
3721 }
3722 } else {
3723 cur++;
3724 }
3725 }
3726 }
3727 break;
3728 case XML_SCHEMAS_LANGUAGE:
3729 if (xmlCheckLanguageID(value) != 1)
3730 ret = 1;
3731 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003732 default: {
3733 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003734 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003735 "Internal error: xmlSchemaPvalueAttrNode, "
3736 "valueidation using the type '%s' is not implemented "
3737 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003738 type->name, NULL);
3739 return (-1);
3740 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003741 }
3742 /*
3743 * TODO: Should we use the S4S error codes instead?
3744 */
3745 if (ret > 0) {
3746 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3747 xmlSchemaPSimpleTypeErr(ctxt,
3748 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3749 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003750 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003751 NULL, NULL, NULL);
3752 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3753 } else {
3754 xmlSchemaPSimpleTypeErr(ctxt,
3755 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3756 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003757 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003758 NULL, NULL, NULL);
3759 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3760 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003761 }
3762 return (ret);
3763}
3764
3765/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003766 * xmlSchemaPValAttrNode:
3767 *
3768 * @ctxt: a schema parser context
3769 * @ownerDes: the designation of the parent element
3770 * @ownerItem: the schema object owner if existent
3771 * @attr: the schema attribute node being validated
3772 * @type: the built-in type to be validated against
3773 * @value: the resulting value if any
3774 *
3775 * Extracts and validates a value against the given built-in type.
3776 * This one is intended to be used internally for validation
3777 * of schema attribute values during parsing of the schema.
3778 *
3779 * Returns 0 if the value is valid, a positive error code
3780 * number otherwise and -1 in case of an internal or API error.
3781 */
3782static int
3783xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3784 xmlChar **ownerDes,
3785 xmlSchemaTypePtr ownerItem,
3786 xmlAttrPtr attr,
3787 xmlSchemaTypePtr type,
3788 const xmlChar **value)
3789{
3790 const xmlChar *val;
3791
3792 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3793 return (-1);
3794
3795 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3796 if (value != NULL)
3797 *value = val;
3798
3799 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3800 val, type));
3801}
3802
3803/**
3804 * xmlSchemaPValAttr:
3805 *
3806 * @ctxt: a schema parser context
3807 * @node: the element node of the attribute
3808 * @ownerDes: the designation of the parent element
3809 * @ownerItem: the schema object owner if existent
3810 * @ownerElem: the owner element node
3811 * @name: the name of the schema attribute node
3812 * @type: the built-in type to be validated against
3813 * @value: the resulting value if any
3814 *
3815 * Extracts and validates a value against the given built-in type.
3816 * This one is intended to be used internally for validation
3817 * of schema attribute values during parsing of the schema.
3818 *
3819 * Returns 0 if the value is valid, a positive error code
3820 * number otherwise and -1 in case of an internal or API error.
3821 */
3822static int
3823xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3824 xmlChar **ownerDes,
3825 xmlSchemaTypePtr ownerItem,
3826 xmlNodePtr ownerElem,
3827 const char *name,
3828 xmlSchemaTypePtr type,
3829 const xmlChar **value)
3830{
3831 xmlAttrPtr attr;
3832
3833 if ((ctxt == NULL) || (type == NULL)) {
3834 if (value != NULL)
3835 *value = NULL;
3836 return (-1);
3837 }
3838 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3839 if (value != NULL)
3840 *value = NULL;
3841 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003842 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003843 "Internal error: xmlSchemaPValAttr, the given "
3844 "type '%s' is not a built-in type.\n",
3845 type->name, NULL);
3846 return (-1);
3847 }
3848 attr = xmlSchemaGetPropNode(ownerElem, name);
3849 if (attr == NULL) {
3850 if (value != NULL)
3851 *value = NULL;
3852 return (0);
3853 }
3854 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
3855 type, value));
3856}
3857/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003858 * xmlSchemaParseAttrDecls:
3859 * @ctxt: a schema validation context
3860 * @schema: the schema being built
3861 * @node: a subtree containing XML Schema informations
3862 * @type: the hosting type
3863 *
3864 * parse a XML schema attrDecls declaration corresponding to
3865 * <!ENTITY % attrDecls
3866 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
3867 */
3868static xmlNodePtr
3869xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3870 xmlNodePtr child, xmlSchemaTypePtr type)
3871{
3872 xmlSchemaAttributePtr lastattr, attr;
3873
3874 lastattr = NULL;
3875 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003876 (IS_SCHEMA(child, "attributeGroup"))) {
3877 attr = NULL;
3878 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003879 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003880 } else if (IS_SCHEMA(child, "attributeGroup")) {
3881 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003882 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883 }
3884 if (attr != NULL) {
3885 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003886 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3887 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
3888 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 type->attributes = attr;
3890 lastattr = attr;
3891 } else {
3892 lastattr->next = attr;
3893 lastattr = attr;
3894 }
3895 }
3896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 }
3898 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003899 xmlSchemaWildcardPtr wildcard;
3900
3901 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
3902 if (wildcard != NULL) {
3903 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3904 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
3905 else
3906 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003907 }
3908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003910 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00003911}
3912
3913/**
3914 * xmlSchemaParseAnnotation:
3915 * @ctxt: a schema validation context
3916 * @schema: the schema being built
3917 * @node: a subtree containing XML Schema informations
3918 *
3919 * parse a XML schema Attrribute declaration
3920 * *WARNING* this interface is highly subject to change
3921 *
William M. Bracke7091952004-05-11 15:09:58 +00003922 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003923 * 1 in case of success.
3924 */
3925static xmlSchemaAnnotPtr
3926xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3927 xmlNodePtr node)
3928{
3929 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003930 xmlNodePtr child = NULL;
3931 xmlAttrPtr attr;
3932 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003933
Daniel Veillardc0826a72004-08-10 14:17:33 +00003934 /*
3935 * INFO: S4S completed.
3936 */
3937 /*
3938 * id = ID
3939 * {any attributes with non-schema namespace . . .}>
3940 * Content: (appinfo | documentation)*
3941 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003942 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3943 return (NULL);
3944 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003945 attr = node->properties;
3946 while (attr != NULL) {
3947 if (((attr->ns == NULL) &&
3948 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
3949 ((attr->ns != NULL) &&
3950 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
3951
3952 xmlSchemaPIllegalAttrErr(ctxt,
3953 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3954 NULL, NULL, attr);
3955 }
3956 attr = attr->next;
3957 }
3958 /* TODO: Check id. */
3959
3960 /*
3961 * And now for the children...
3962 */
3963 child = node->children;
3964 while (child != NULL) {
3965 if (IS_SCHEMA(child, "appinfo")) {
3966 /* TODO: make available the content of "appinfo". */
3967 /*
3968 * source = anyURI
3969 * {any attributes with non-schema namespace . . .}>
3970 * Content: ({any})*
3971 */
3972 attr = child->properties;
3973 while (attr != NULL) {
3974 if (((attr->ns == NULL) &&
3975 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
3976 ((attr->ns != NULL) &&
3977 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003978
Daniel Veillardc0826a72004-08-10 14:17:33 +00003979 xmlSchemaPIllegalAttrErr(ctxt,
3980 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3981 NULL, NULL, attr);
3982 }
3983 attr = attr->next;
3984 }
3985 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
3986 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
3987 child = child->next;
3988 } else if (IS_SCHEMA(child, "documentation")) {
3989 /* TODO: make available the content of "documentation". */
3990 /*
3991 * source = anyURI
3992 * {any attributes with non-schema namespace . . .}>
3993 * Content: ({any})*
3994 */
3995 attr = child->properties;
3996 while (attr != NULL) {
3997 if (attr->ns == NULL) {
3998 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
3999 xmlSchemaPIllegalAttrErr(ctxt,
4000 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4001 NULL, NULL, attr);
4002 }
4003 } else {
4004 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4005 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4006 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4007
4008 xmlSchemaPIllegalAttrErr(ctxt,
4009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4010 NULL, NULL, attr);
4011 }
4012 }
4013 attr = attr->next;
4014 }
4015 /*
4016 * Attribute "xml:lang".
4017 */
4018 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4019 if (attr != NULL)
4020 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4021 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4022 child = child->next;
4023 } else {
4024 if (!barked)
4025 xmlSchemaPContentErr(ctxt,
4026 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4027 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4028 barked = 1;
4029 child = child->next;
4030 }
4031 }
4032
Daniel Veillard4255d502002-04-16 15:50:10 +00004033 return (ret);
4034}
4035
4036/**
4037 * xmlSchemaParseFacet:
4038 * @ctxt: a schema validation context
4039 * @schema: the schema being built
4040 * @node: a subtree containing XML Schema informations
4041 *
4042 * parse a XML schema Facet declaration
4043 * *WARNING* this interface is highly subject to change
4044 *
4045 * Returns the new type structure or NULL in case of error
4046 */
4047static xmlSchemaFacetPtr
4048xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004049 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004050{
4051 xmlSchemaFacetPtr facet;
4052 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004053 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004054
4055 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4056 return (NULL);
4057
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004058 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004059 if (facet == NULL) {
4060 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4061 return (NULL);
4062 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004063 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004064 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004065 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004066 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4067 "Facet %s has no value\n", node->name, NULL);
4068 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004069 return (NULL);
4070 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004071 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004073 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004074 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004075 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004076 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004077 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004078 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004079 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004080 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004081 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004082 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004083 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004084 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004085 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004086 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004087 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004088 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004089 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004090 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004091 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004092 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4093 } else if (IS_SCHEMA(node, "minLength")) {
4094 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4095 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4097 "Unknown facet type %s\n", node->name, NULL);
4098 xmlSchemaFreeFacet(facet);
4099 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004100 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004101 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004102 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004103 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4104 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4105 const xmlChar *fixed;
4106
4107 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4108 if (fixed != NULL) {
4109 if (xmlStrEqual(fixed, BAD_CAST "true"))
4110 facet->fixed = 1;
4111 }
4112 }
4113
Daniel Veillard4255d502002-04-16 15:50:10 +00004114 child = node->children;
4115
4116 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004117 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4118 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004119 }
4120 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004121 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4122 "Facet %s has unexpected child content\n",
4123 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004124 }
4125 return (facet);
4126}
4127
4128/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004129 * xmlSchemaParseWildcardNs:
4130 * @ctxt: a schema parser context
4131 * @wildc: the wildcard, already created
4132 * @node: a subtree containing XML Schema informations
4133 *
4134 * Parses the attribute "processContents" and "namespace"
4135 * of a xsd:anyAttribute and xsd:any.
4136 * *WARNING* this interface is highly subject to change
4137 *
4138 * Returns 0 if everything goes fine, a positive error code
4139 * if something is not valid and -1 if an internal error occurs.
4140 */
4141static int
4142xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4143 xmlSchemaPtr schema,
4144 xmlSchemaWildcardPtr wildc,
4145 xmlNodePtr node)
4146{
4147 const xmlChar *pc, *ns, *dictnsItem;
4148 int ret = 0;
4149 xmlChar *nsItem;
4150 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4151 xmlAttrPtr attr;
4152
4153 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4154 if ((pc == NULL)
4155 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4156 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4157 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4158 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4159 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4160 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4161 } else {
4162 xmlSchemaPSimpleTypeErr(ctxt,
4163 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4164 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004165 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004166 NULL, NULL, NULL);
4167 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4168 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4169 }
4170 /*
4171 * Build the namespace constraints.
4172 */
4173 attr = xmlSchemaGetPropNode(node, "namespace");
4174 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4175 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4176 wildc->any = 1;
4177 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4178 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4179 if (wildc->negNsSet == NULL) {
4180 return (-1);
4181 }
4182 wildc->negNsSet->value = schema->targetNamespace;
4183 } else {
4184 const xmlChar *end, *cur;
4185
4186 cur = ns;
4187 do {
4188 while (IS_BLANK_CH(*cur))
4189 cur++;
4190 end = cur;
4191 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4192 end++;
4193 if (end == cur)
4194 break;
4195 nsItem = xmlStrndup(cur, end - cur);
4196 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4197 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4198 xmlSchemaPSimpleTypeErr(ctxt,
4199 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4200 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004201 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004202 "((##any | ##other) | List of (anyURI | "
4203 "(##targetNamespace | ##local)))",
4204 nsItem, NULL, NULL, NULL);
4205 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4206 } else {
4207 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4208 dictnsItem = schema->targetNamespace;
4209 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4210 dictnsItem = NULL;
4211 } else {
4212 /*
4213 * Validate the item (anyURI).
4214 */
4215 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4216 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4217 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4218 }
4219 /*
4220 * Avoid dublicate namespaces.
4221 */
4222 tmp = wildc->nsSet;
4223 while (tmp != NULL) {
4224 if (dictnsItem == tmp->value)
4225 break;
4226 tmp = tmp->next;
4227 }
4228 if (tmp == NULL) {
4229 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4230 if (tmp == NULL) {
4231 xmlFree(nsItem);
4232 return (-1);
4233 }
4234 tmp->value = dictnsItem;
4235 tmp->next = NULL;
4236 if (wildc->nsSet == NULL)
4237 wildc->nsSet = tmp;
4238 else
4239 lastNs->next = tmp;
4240 lastNs = tmp;
4241 }
4242
4243 }
4244 xmlFree(nsItem);
4245 cur = end;
4246 } while (*cur != 0);
4247 }
4248 return (ret);
4249}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004250
4251static int
4252xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4253 xmlSchemaTypePtr item,
4254 xmlNodePtr node,
4255 int minOccurs,
4256 int maxOccurs) {
4257
4258 if (maxOccurs != UNBOUNDED) {
4259 /*
4260 * TODO: Maby we should better not create the particle,
4261 * if min/max is invalid, since it could confuse the build of the
4262 * content model.
4263 */
4264 /*
4265 * 3.9.6 Schema Component Constraint: Particle Correct
4266 *
4267 */
4268 if (maxOccurs < 1) {
4269 /*
4270 * 2.2 {max occurs} must be greater than or equal to 1.
4271 */
4272 xmlSchemaPCustomAttrErr(ctxt,
4273 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4274 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4275 "The value must be greater than or equal to 1");
4276 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4277 } else if (minOccurs > maxOccurs) {
4278 /*
4279 * 2.1 {min occurs} must not be greater than {max occurs}.
4280 */
4281 xmlSchemaPCustomAttrErr(ctxt,
4282 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4283 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4284 "The value must not be greater than the value of 'maxOccurs'");
4285 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4286 }
4287 }
4288 return (0);
4289}
4290
Daniel Veillardc0826a72004-08-10 14:17:33 +00004291/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004292 * xmlSchemaParseAny:
4293 * @ctxt: a schema validation context
4294 * @schema: the schema being built
4295 * @node: a subtree containing XML Schema informations
4296 *
4297 * parse a XML schema Any declaration
4298 * *WARNING* this interface is highly subject to change
4299 *
4300 * Returns the new type structure or NULL in case of error
4301 */
4302static xmlSchemaTypePtr
4303xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4304 xmlNodePtr node)
4305{
4306 xmlSchemaTypePtr type;
4307 xmlNodePtr child = NULL;
4308 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004309 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004310 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004311
4312 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4313 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004314 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4315 "(nonNegativeInteger | unbounded)");
4316 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4317 "nonNegativeInteger");
4318 if ((minOccurs == 0) && (maxOccurs == 0))
4319 return (NULL);
4320
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004321 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004322 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004325 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004326 type->type = XML_SCHEMA_TYPE_ANY;
4327
Daniel Veillardc0826a72004-08-10 14:17:33 +00004328 wildc = xmlSchemaAddWildcard(ctxt);
4329 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004330 * Check min/max sanity.
4331 */
4332 type->maxOccurs = maxOccurs;
4333 type->minOccurs = minOccurs;
4334 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4335 node, type->minOccurs, type->maxOccurs);
4336 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004337 * This is not nice, since it is won't be used as a attribute wildcard,
4338 * but better than adding a field to the structure.
4339 */
4340 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004341 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004342 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004344 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4345 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004346 }
4347 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004348 xmlSchemaPErr2(ctxt, node, child,
4349 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4350 "Sequence %s has unexpected content\n", type->name,
4351 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004352 }
4353
4354 return (type);
4355}
4356
4357/**
4358 * xmlSchemaParseNotation:
4359 * @ctxt: a schema validation context
4360 * @schema: the schema being built
4361 * @node: a subtree containing XML Schema informations
4362 *
4363 * parse a XML schema Notation declaration
4364 *
4365 * Returns the new structure or NULL in case of error
4366 */
4367static xmlSchemaNotationPtr
4368xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004369 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004370{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004371 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 xmlSchemaNotationPtr ret;
4373 xmlNodePtr child = NULL;
4374
4375 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4376 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004377 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004379 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4380 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 return (NULL);
4382 }
4383 ret = xmlSchemaAddNotation(ctxt, schema, name);
4384 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004385 return (NULL);
4386 }
4387 child = node->children;
4388 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004389 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4390 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004391 }
4392 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004393 xmlSchemaPErr2(ctxt, node, child,
4394 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4395 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 }
4397
4398 return (ret);
4399}
4400
4401/**
4402 * xmlSchemaParseAnyAttribute:
4403 * @ctxt: a schema validation context
4404 * @schema: the schema being built
4405 * @node: a subtree containing XML Schema informations
4406 *
4407 * parse a XML schema AnyAttrribute declaration
4408 * *WARNING* this interface is highly subject to change
4409 *
4410 * Returns an attribute def structure or NULL
4411 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004412static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4414 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004415{
Daniel Veillard3646d642004-06-02 19:19:14 +00004416 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004418
4419 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4420 return (NULL);
4421
Daniel Veillard3646d642004-06-02 19:19:14 +00004422 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004423 if (ret == NULL) {
4424 return (NULL);
4425 }
William M. Bracke7091952004-05-11 15:09:58 +00004426 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004427 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004428 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4429 xmlSchemaFreeWildcard(ret);
4430 return (NULL);
4431 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 child = node->children;
4433 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004434 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4435 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004436 }
4437 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004438 /* TODO: Change the error code. */
4439 xmlSchemaPContentErr(ctxt,
4440 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
4441 NULL, NULL, node, child,
4442 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 }
4444
4445 return (ret);
4446}
4447
4448
4449/**
4450 * xmlSchemaParseAttribute:
4451 * @ctxt: a schema validation context
4452 * @schema: the schema being built
4453 * @node: a subtree containing XML Schema informations
4454 *
4455 * parse a XML schema Attrribute declaration
4456 * *WARNING* this interface is highly subject to change
4457 *
William M. Bracke7091952004-05-11 15:09:58 +00004458 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004459 */
4460static xmlSchemaAttributePtr
4461xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004462 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004463{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004464 const xmlChar *name, *attrValue;
4465 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004466 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004467 xmlNodePtr child = NULL;
4468 xmlAttrPtr attr, nameAttr;
4469 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004470
4471 /*
4472 * Note that the w3c spec assumes the schema to be validated with schema
4473 * for schemas beforehand.
4474 *
4475 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004477
4478 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4479 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004480 attr = xmlSchemaGetPropNode(node, "ref");
4481 nameAttr = xmlSchemaGetPropNode(node, "name");
4482
4483 if ((attr == NULL) && (nameAttr == NULL)) {
4484 /*
4485 * 3.2.3 : 3.1
4486 * One of ref or name must be present, but not both
4487 */
4488 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4489 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4490 "One of the attributes 'ref' or 'name' must be present");
4491 return (NULL);
4492 }
4493 if ((topLevel) || (attr == NULL)) {
4494 if (nameAttr == NULL) {
4495 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4496 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4497 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004498 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004499 }
4500 } else
4501 isRef = 1;
4502
4503 if (isRef) {
4504 char buf[100];
4505 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4506
4507 /*
4508 * Parse as attribute reference.
4509 */
4510 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4511 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4512 &refPrefix, &ref) != 0) {
4513 return (NULL);
4514 }
4515 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4516 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004517 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004518 if (ret == NULL) {
4519 if (repName != NULL)
4520 xmlFree(repName);
4521 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004522 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004523 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4524 ret->node = node;
4525 ret->refNs = refNs;
4526 ret->refPrefix = refPrefix;
4527 ret->ref = ref;
4528 /*
4529 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4530 */
4531 if (nameAttr != NULL)
4532 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4533 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4534 "ref", "name");
4535 /*
4536 * Check for illegal attributes.
4537 */
4538 attr = node->properties;
4539 while (attr != NULL) {
4540 if (attr->ns == NULL) {
4541 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4542 xmlStrEqual(attr->name, BAD_CAST "form")) {
4543 /*
4544 * 3.2.3 : 3.2
4545 * If ref is present, then all of <simpleType>,
4546 * form and type must be absent.
4547 */
4548 xmlSchemaPIllegalAttrErr(ctxt,
4549 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4550 (xmlSchemaTypePtr) ret, attr);
4551 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4552 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4553 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4554 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4555 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4556 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4557 xmlSchemaPIllegalAttrErr(ctxt,
4558 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4559 &repName, (xmlSchemaTypePtr) ret, attr);
4560 }
4561 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4562 xmlSchemaPIllegalAttrErr(ctxt,
4563 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4564 &repName, (xmlSchemaTypePtr) ret, attr);
4565 }
4566 attr = attr->next;
4567 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004568 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004569 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004570
4571 /*
4572 * Parse as attribute declaration.
4573 */
4574 if (xmlSchemaPValAttrNode(ctxt,
4575 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4576 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4577 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004578 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004579 /*
4580 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4581 */
4582 /*
4583 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4584 */
4585 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4586 xmlSchemaPSimpleTypeErr(ctxt,
4587 XML_SCHEMAP_NO_XMLNS,
4588 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004589 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004590 "The value must not match 'xmlns'",
4591 NULL, NULL);
4592 if (repName != NULL)
4593 xmlFree(repName);
4594 return (NULL);
4595 }
4596 /*
4597 * Evaluate the target namespace
4598 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004599 if (topLevel) {
4600 ns = schema->targetNamespace;
4601 } else {
4602 attr = xmlSchemaGetPropNode(node, "form");
4603 if (attr != NULL) {
4604 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4605 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4606 ns = schema->targetNamespace;
4607 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4608 xmlSchemaPSimpleTypeErr(ctxt,
4609 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4610 &repName, NULL, (xmlNodePtr) attr,
4611 NULL, "(qualified | unqualified)",
4612 attrValue, NULL, NULL, NULL);
4613 }
4614 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4615 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004616 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004617 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004618 if (ret == NULL) {
4619 if (repName != NULL)
4620 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004621 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004622 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004623 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4624 ret->node = node;
4625 if (topLevel)
4626 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4627 /*
4628 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4629 */
4630 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4631 xmlSchemaPCustomErr(ctxt,
4632 XML_SCHEMAP_NO_XSI,
4633 &repName, (xmlSchemaTypePtr) ret, node,
4634 "The target namespace must not match '%s'",
4635 xmlSchemaInstanceNs);
4636 }
4637 /*
4638 * Check for illegal attributes.
4639 */
4640 attr = node->properties;
4641 while (attr != NULL) {
4642 if (attr->ns == NULL) {
4643 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4644 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4645 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4646 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4647 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4648 if ((topLevel) ||
4649 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4650 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4651 xmlSchemaPIllegalAttrErr(ctxt,
4652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4653 &repName, (xmlSchemaTypePtr) ret, attr);
4654 }
4655 }
4656 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4657 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4658 &repName, (xmlSchemaTypePtr) ret, attr);
4659 }
4660 attr = attr->next;
4661 }
4662 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4663 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004664 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004665 /* TODO: Check ID. */
4666 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004667 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004668 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004669 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004670 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4671 if (ret->defValue != NULL)
4672 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4673 /*
4674 * Attribute "default".
4675 */
4676 attr = xmlSchemaGetPropNode(node, "default");
4677 if (attr != NULL) {
4678 /*
4679 * 3.2.3 : 1
4680 * default and fixed must not both be present.
4681 */
4682 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4683 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4684 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4685 } else
4686 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4687 }
4688 if (topLevel == 0) {
4689 /*
4690 * Attribute "use".
4691 */
4692 attr = xmlSchemaGetPropNode(node, "use");
4693 if (attr != NULL) {
4694 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4695 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4696 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4697 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4698 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4699 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4700 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4701 else
4702 xmlSchemaPSimpleTypeErr(ctxt,
4703 XML_SCHEMAP_INVALID_ATTR_USE,
4704 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004705 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004706 attrValue, NULL, NULL, NULL);
4707 } else
4708 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4709 /*
4710 * 3.2.3 : 2
4711 * If default and use are both present, use must have
4712 * the actual value optional.
4713 */
4714 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4715 (ret->defValue != NULL) &&
4716 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4717 xmlSchemaPSimpleTypeErr(ctxt,
4718 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4719 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004720 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004721 "The value must be 'optional' if the attribute "
4722 "'default' is present as well", NULL, NULL);
4723 }
4724 }
4725 /*
4726 * And now for the children...
4727 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004728 child = node->children;
4729 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004730 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4731 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004732 }
4733 if (isRef) {
4734 if (child != NULL) {
4735 if (IS_SCHEMA(child, "simpleType"))
4736 /*
4737 * 3.2.3 : 3.2
4738 * If ref is present, then all of <simpleType>,
4739 * form and type must be absent.
4740 */
4741 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4742 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4743 "(annotation?)");
4744 else
4745 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4746 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4747 "(annotation?)");
4748 }
4749 } else {
4750 if (IS_SCHEMA(child, "simpleType")) {
4751 if (ret->typeName != NULL) {
4752 /*
4753 * 3.2.3 : 4
4754 * type and <simpleType> must not both be present.
4755 */
4756 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4757 &repName, (xmlSchemaTypePtr) ret, node, child,
4758 "The attribute 'type' and the <simpleType> child "
4759 "are mutually exclusive", NULL);
4760 } else
4761 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4762 child = child->next;
4763 }
4764 if (child != NULL)
4765 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4766 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4767 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004768 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004769 /*
4770 * Cleanup.
4771 */
4772 if (repName != NULL)
4773 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004774 return (ret);
4775}
4776
4777/**
4778 * xmlSchemaParseAttributeGroup:
4779 * @ctxt: a schema validation context
4780 * @schema: the schema being built
4781 * @node: a subtree containing XML Schema informations
4782 *
4783 * parse a XML schema Attribute Group declaration
4784 * *WARNING* this interface is highly subject to change
4785 *
4786 * Returns the attribute group or NULL in case of error.
4787 */
4788static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004790 xmlSchemaPtr schema, xmlNodePtr node,
4791 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004792{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004793 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004795 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004796 const xmlChar *oldcontainer;
4797 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004798
4799 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4800 return (NULL);
4801 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004802 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004803 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
4805 if (ref == NULL) {
4806 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004807 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
4808 "Attribute group or particle: One of the attributes 'name' "
4809 "or 'ref' must be present.\n", NULL,
4810 NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004811 return (NULL);
4812 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004813 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
4814 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 if (name == NULL) {
4816 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
4817 return (NULL);
4818 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004819 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004820 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004822 return (NULL);
4823 }
4824 ret->ref = ref;
4825 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004826 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00004827 if (topLevel)
4828 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004829 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 child = node->children;
4831 ctxt->container = name;
4832 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4834 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004835 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004836 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004837 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004838 xmlSchemaPErr2(ctxt, node, child,
4839 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004840 "Attribute group '%s' has unexpected content.\n", name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004841 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004842 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004843 ctxt->container = oldcontainer;
4844 return (ret);
4845}
4846
4847/**
William M. Brack2f2a6632004-08-20 23:09:47 +00004848 * xmlSchemaPValAttrFormDefault:
4849 * @value: the value
4850 * @flags: the flags to be modified
4851 * @flagQualified: the specific flag for "qualified"
4852 *
4853 * Returns 0 if the value is valid, 1 otherwise.
4854 */
4855static int
4856xmlSchemaPValAttrFormDefault(const xmlChar *value,
4857 int *flags,
4858 int flagQualified)
4859{
4860 if (xmlStrEqual(value, BAD_CAST "qualified")) {
4861 if ((*flags & flagQualified) == 0)
4862 *flags |= flagQualified;
4863 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
4864 return (1);
4865
4866 return (0);
4867}
4868
4869/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004870 * xmlSchemaPValAttrBlockFinal:
4871 * @value: the value
4872 * @flags: the flags to be modified
4873 * @flagAll: the specific flag for "#all"
4874 * @flagExtension: the specific flag for "extension"
4875 * @flagRestriction: the specific flag for "restriction"
4876 * @flagSubstitution: the specific flag for "substitution"
4877 * @flagList: the specific flag for "list"
4878 * @flagUnion: the specific flag for "union"
4879 *
4880 * Validates the value of the attribute "final" and "block". The value
4881 * is converted into the specified flag values and returned in @flags.
4882 *
4883 * Returns 0 if the value is valid, 1 otherwise.
4884 */
4885
4886static int
4887xmlSchemaPValAttrBlockFinal(const xmlChar *value,
4888 int *flags,
4889 int flagAll,
4890 int flagExtension,
4891 int flagRestriction,
4892 int flagSubstitution,
4893 int flagList,
4894 int flagUnion)
4895{
4896 int ret = 0;
4897
4898 /*
4899 * TODO: This does not check for dublicate entries.
4900 */
William M. Brack2f2a6632004-08-20 23:09:47 +00004901 if (value == NULL)
4902 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004903 if (xmlStrEqual(value, BAD_CAST "#all")) {
4904 if (flagAll != -1)
4905 *flags |= flagAll;
4906 else {
4907 if (flagExtension != -1)
4908 *flags |= flagExtension;
4909 if (flagRestriction != -1)
4910 *flags |= flagRestriction;
4911 if (flagSubstitution != -1)
4912 *flags |= flagSubstitution;
4913 if (flagList != -1)
4914 *flags |= flagList;
4915 if (flagUnion != -1)
4916 *flags |= flagUnion;
4917 }
4918 } else {
4919 const xmlChar *end, *cur = value;
4920 xmlChar *item;
4921
4922 do {
4923 while (IS_BLANK_CH(*cur))
4924 cur++;
4925 end = cur;
4926 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4927 end++;
4928 if (end == cur)
4929 break;
4930 item = xmlStrndup(cur, end - cur);
4931 if (xmlStrEqual(item, BAD_CAST "extension")) {
4932 if (flagExtension != -1) {
4933 if ((*flags & flagExtension) == 0)
4934 *flags |= flagExtension;
4935 } else
4936 ret = 1;
4937 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4938 if (flagRestriction != -1) {
4939 if ((*flags & flagRestriction) == 0)
4940 *flags |= flagRestriction;
4941 } else
4942 ret = 1;
4943 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
4944 if (flagSubstitution != -1) {
4945 if ((*flags & flagSubstitution) == 0)
4946 *flags |= flagSubstitution;
4947 } else
4948 ret = 1;
4949 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4950 if (flagList != -1) {
4951 if ((*flags & flagList) == 0)
4952 *flags |= flagList;
4953 } else
4954 ret = 1;
4955 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4956 if (flagUnion != -1) {
4957 if ((*flags & flagUnion) == 0)
4958 *flags |= flagUnion;
4959 } else
4960 ret = 1;
4961 } else
4962 ret = 1;
4963 if (item != NULL)
4964 xmlFree(item);
4965 cur = end;
4966 } while ((ret == 0) && (*cur != 0));
4967 }
4968
4969 return (ret);
4970}
4971
4972/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004973 * xmlSchemaParseElement:
4974 * @ctxt: a schema validation context
4975 * @schema: the schema being built
4976 * @node: a subtree containing XML Schema informations
4977 *
4978 * parse a XML schema Element declaration
4979 * *WARNING* this interface is highly subject to change
4980 *
William M. Bracke7091952004-05-11 15:09:58 +00004981 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 */
4983static xmlSchemaElementPtr
4984xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004985 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004986{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004987 const xmlChar *name = NULL;
4988 const xmlChar *attrValue;
4989 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004990 xmlSchemaElementPtr ret;
4991 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004992 const xmlChar *oldcontainer;
4993 xmlAttrPtr attr, nameAttr;
4994 int minOccurs, maxOccurs;
4995 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004996
4997 /* 3.3.3 Constraints on XML Representations of Element Declarations */
4998 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5001 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005002
Daniel Veillardc0826a72004-08-10 14:17:33 +00005003 oldcontainer = ctxt->container;
5004
5005 nameAttr = xmlSchemaGetPropNode(node, "name");
5006 attr = xmlSchemaGetPropNode(node, "ref");
5007 if ((topLevel) || (attr == NULL)) {
5008 if (nameAttr == NULL) {
5009 xmlSchemaPMissingAttrErr(ctxt,
5010 XML_SCHEMAP_S4S_ATTR_MISSING,
5011 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5012 "name", NULL);
5013 return (NULL);
5014 }
5015 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5016 } else {
5017 isRef = 1;
5018
5019 }
5020 /*
5021 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5022 * to no component at all
5023 * TODO: It might be better to validate the element, even if it won't be
5024 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005025 */
5026 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5027 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005028 if ((minOccurs == 0) && (maxOccurs == 0))
5029 return (NULL);
5030 /*
5031 * If we get a "ref" attribute on a local <element> we will assume it's
5032 * a reference - even if there's a "name" attribute; this seems to be more
5033 * robust.
5034 */
5035 if (isRef) {
5036 char buf[100];
5037 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5038
5039 /*
5040 * Parse as a particle.
5041 */
5042 xmlSchemaPValAttrNodeQName(ctxt, schema,
5043 (xmlChar **) &xmlSchemaElemDesAttrRef,
5044 NULL, attr, &refNs, &refPrefix, &ref);
5045
5046 snprintf(buf, 99, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005047 name = (const xmlChar *) buf;
5048 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005049 if (ret == NULL) {
5050 if (repName != NULL)
5051 xmlFree(repName);
5052 return (NULL);
5053 }
5054 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5055 ret->node = node;
5056 ret->ref = ref;
5057 ret->refNs = refNs;
5058 ret->refPrefix = refPrefix;
5059 ret->flags |= XML_SCHEMAS_ELEM_REF;
5060 /*
5061 * Check for illegal attributes.
5062 */
5063 /*
5064 * 3.3.3 : 2.1
5065 * One of ref or name must be present, but not both
5066 */
5067 if (nameAttr != NULL) {
5068 xmlSchemaPMutualExclAttrErr(ctxt,
5069 XML_SCHEMAP_SRC_ELEMENT_2_1,
5070 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5071 "ref", "name");
5072 }
5073 /* 3.3.3 : 2.2 */
5074 attr = node->properties;
5075 while (attr != NULL) {
5076 if (attr->ns == NULL) {
5077 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5078 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5079 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5080 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5081 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
5082 xmlSchemaPCustomAttrErr(ctxt,
5083 XML_SCHEMAP_SRC_ELEMENT_2_2,
5084 &repName, (xmlSchemaTypePtr) ret, attr,
5085 "Only the attributes 'minOccurs', 'maxOccurs' and "
5086 "'id' are allowed in addition to 'ref'");
5087 break;
5088 }
5089 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5090 xmlSchemaPIllegalAttrErr(ctxt,
5091 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5092 &repName, (xmlSchemaTypePtr) ret, attr);
5093 }
5094 attr = attr->next;
5095 }
5096 } else {
5097 const xmlChar *ns = NULL, *fixed;
5098
5099 /*
5100 * Parse as an element declaration.
5101 */
5102 if (xmlSchemaPValAttrNode(ctxt,
5103 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5104 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5105 return (NULL);
5106 /*
5107 * Evaluate the target namespace.
5108 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005109 if (topLevel) {
5110 ns = schema->targetNamespace;
5111 } else {
5112 attr = xmlSchemaGetPropNode(node, "form");
5113 if (attr != NULL) {
5114 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5115 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005116 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005117 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5118 xmlSchemaPSimpleTypeErr(ctxt,
5119 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5120 &repName, NULL, (xmlNodePtr) attr,
5121 NULL, "(qualified | unqualified)",
5122 attrValue, NULL, NULL, NULL);
5123 }
5124 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5125 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005126 }
5127 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005128 if (ret == NULL) {
5129 if (repName != NULL)
5130 xmlFree(repName);
5131 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005132 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005133 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5134 ret->node = node;
5135 /*
5136 * Check for illegal attributes.
5137 */
William M. Bracke7091952004-05-11 15:09:58 +00005138 attr = node->properties;
5139 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005140 if (attr->ns == NULL) {
5141 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5142 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5143 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5144 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5145 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5146 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
5147 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
5148 if (topLevel == 0) {
5149 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5150 /*
5151 * 3.3.6 : 3 If there is a non-·absent· {substitution
5152 * group affiliation}, then {scope} must be global.
5153 * TODO: This one is redundant, since the S4S does
5154 * prohibit this attribute on local declarations already;
5155 * so why an explicit error code? Weird spec.
William M. Brack2f2a6632004-08-20 23:09:47 +00005156 * TODO: Move this to the proper constraint layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005157 */
5158 xmlSchemaPIllegalAttrErr(ctxt,
5159 XML_SCHEMAP_E_PROPS_CORRECT_3,
5160 &repName, (xmlSchemaTypePtr) ret, attr);
5161 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5162 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5163 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005164
Daniel Veillardc0826a72004-08-10 14:17:33 +00005165 xmlSchemaPIllegalAttrErr(ctxt,
5166 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5167 &repName, (xmlSchemaTypePtr) ret, attr);
5168 }
5169 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5170 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5171 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5172
5173 xmlSchemaPIllegalAttrErr(ctxt,
5174 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5175 &repName, (xmlSchemaTypePtr) ret, attr);
5176 }
5177 }
5178 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5179
5180 xmlSchemaPIllegalAttrErr(ctxt,
5181 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5182 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005183 }
5184 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005185 }
William M. Bracke7091952004-05-11 15:09:58 +00005186 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005187 * Extract/validate attributes.
5188 */
5189 if (topLevel) {
5190 /*
5191 * Process top attributes of global element declarations here.
5192 */
5193 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5194 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5195 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5196 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5197 &(ret->substGroupNs), NULL, &(ret->substGroup));
5198 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5199 node, "abstract", 0))
5200 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5201 /*
5202 * Attribute "final".
5203 */
5204 attr = xmlSchemaGetPropNode(node, "final");
5205 if (attr == NULL) {
5206 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5207 } else {
5208 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5209 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5210 -1,
5211 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5212 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5213 xmlSchemaPSimpleTypeErr(ctxt,
5214 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5215 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005216 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005217 attrValue, NULL, NULL, NULL);
5218 }
5219 }
5220 }
5221 /*
5222 * Attribute "block".
5223 */
5224 attr = xmlSchemaGetPropNode(node, "block");
5225 if (attr == NULL) {
5226 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5227 } else {
5228 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5229 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5230 -1,
5231 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5232 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5233 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5234 xmlSchemaPSimpleTypeErr(ctxt,
5235 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5236 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005237 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005238 "restriction | substitution))", attrValue,
5239 NULL, NULL, NULL);
5240 }
5241 }
5242 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5243 node, "nillable", 0))
5244 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005245
Daniel Veillardc0826a72004-08-10 14:17:33 +00005246 xmlSchemaPValAttrQName(ctxt, schema,
5247 &repName, (xmlSchemaTypePtr) ret, node,
5248 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005249
Daniel Veillardc0826a72004-08-10 14:17:33 +00005250 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5251 attr = xmlSchemaGetPropNode(node, "fixed");
5252 if (attr != NULL) {
5253 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5254 if (ret->value != NULL) {
5255 /*
5256 * 3.3.3 : 1
5257 * default and fixed must not both be present.
5258 */
5259 xmlSchemaPMutualExclAttrErr(ctxt,
5260 XML_SCHEMAP_SRC_ELEMENT_1,
5261 &repName, (xmlSchemaTypePtr) ret, attr,
5262 "default", "fixed");
5263 } else {
5264 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5265 ret->value = fixed;
5266 }
5267 }
5268 }
5269 /*
5270 * Extract/validate common attributes.
5271 */
5272 /* TODO: Check ID: */
5273 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5274 ret->minOccurs = minOccurs;
5275 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 if (topLevel != 1)
5277 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5278 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005279 /*
5280 * And now for the children...
5281 */
5282 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005283 child = node->children;
5284 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005285 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5286 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005288 if (isRef) {
5289 if (child != NULL) {
5290 xmlSchemaPContentErr(ctxt,
5291 XML_SCHEMAP_SRC_ELEMENT_2_2,
5292 &repName, (xmlSchemaTypePtr) ret, node, child,
5293 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005294 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005295 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005296 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005297 /*
5298 * 3.3.3 : 3
5299 * "type" and either <simpleType> or <complexType> are mutually
5300 * exclusive
5301 */
William M. Bracke7091952004-05-11 15:09:58 +00005302 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005303 xmlSchemaPContentErr(ctxt,
5304 XML_SCHEMAP_SRC_ELEMENT_3,
5305 &repName, (xmlSchemaTypePtr) ret, node, child,
5306 "The attribute 'type' and the <complexType> child are "
5307 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005308 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005309 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005310 child = child->next;
5311 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005312 /*
5313 * 3.3.3 : 3
5314 * "type" and either <simpleType> or <complexType> are
5315 * mutually exclusive
5316 */
William M. Bracke7091952004-05-11 15:09:58 +00005317 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005318 xmlSchemaPContentErr(ctxt,
5319 XML_SCHEMAP_SRC_ELEMENT_3,
5320 &repName, (xmlSchemaTypePtr) ret, node, child,
5321 "The attribute 'type' and the <simpleType> child are "
5322 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005323 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005324 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005325 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005326 }
William M. Bracke7091952004-05-11 15:09:58 +00005327 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005328 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005329 TODO child = child->next;
5330 }
5331 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005332 xmlSchemaPContentErr(ctxt,
5333 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5334 &repName, (xmlSchemaTypePtr) ret, node, child,
5335 NULL, "(annotation?, ((simpleType | complexType)?, "
5336 "(unique | key | keyref)*))");
5337 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005338
Daniel Veillardc0826a72004-08-10 14:17:33 +00005339 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005340 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 /*
5342 * Cleanup.
5343 */
5344 if (repName != NULL)
5345 xmlFree(repName);
5346 /*
5347 * NOTE: Element Declaration Representation OK 4. will be checked at a
5348 * different layer.
5349 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005350 return (ret);
5351}
5352
5353/**
5354 * xmlSchemaParseUnion:
5355 * @ctxt: a schema validation context
5356 * @schema: the schema being built
5357 * @node: a subtree containing XML Schema informations
5358 *
5359 * parse a XML schema Union definition
5360 * *WARNING* this interface is highly subject to change
5361 *
William M. Bracke7091952004-05-11 15:09:58 +00005362 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005363 * 1 in case of success.
5364 */
5365static xmlSchemaTypePtr
5366xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005367 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005368{
5369 xmlSchemaTypePtr type, subtype, last = NULL;
5370 xmlNodePtr child = NULL;
5371 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005372 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005373
5374 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5375 return (NULL);
5376
William M. Brack2f2a6632004-08-20 23:09:47 +00005377 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5378 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005379 if (type == NULL)
5380 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005381 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005382 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005383 /*
5384 * Check for illegal attributes.
5385 */
5386 attr = node->properties;
5387 while (attr != NULL) {
5388 if (attr->ns == NULL) {
5389 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5390 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5391 xmlSchemaPIllegalAttrErr(ctxt,
5392 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5393 NULL, type, attr);
5394 }
5395 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5396 xmlSchemaPIllegalAttrErr(ctxt,
5397 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5398 NULL, type, attr);
5399 }
5400 attr = attr->next;
5401 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005402 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005403 /*
5404 * Attribute "memberTypes". This is a list of QNames.
5405 * TODO: Validate the QNames.
5406 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005407 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005408 /*
5409 * And now for the children...
5410 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005411 child = node->children;
5412 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5414 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005416 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005418 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005419 if (subtype != NULL) {
5420 if (last == NULL) {
5421 type->subtypes = subtype;
5422 last = subtype;
5423 } else {
5424 last->next = subtype;
5425 last = subtype;
5426 }
5427 last->next = NULL;
5428 }
5429 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005430 }
5431 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005432 /* TODO: Think about the error code. */
5433 xmlSchemaPContentErr(ctxt,
5434 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5435 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 }
5437 return (type);
5438}
5439
5440/**
5441 * xmlSchemaParseList:
5442 * @ctxt: a schema validation context
5443 * @schema: the schema being built
5444 * @node: a subtree containing XML Schema informations
5445 *
5446 * parse a XML schema List definition
5447 * *WARNING* this interface is highly subject to change
5448 *
William M. Bracke7091952004-05-11 15:09:58 +00005449 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005450 * 1 in case of success.
5451 */
5452static xmlSchemaTypePtr
5453xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005454 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005455{
5456 xmlSchemaTypePtr type, subtype;
5457 xmlNodePtr child = NULL;
5458 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005459 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005460
5461 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5462 return (NULL);
5463
William M. Brack2f2a6632004-08-20 23:09:47 +00005464 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5465 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005466 if (type == NULL)
5467 return (NULL);
5468 type->node = node;
5469 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005470 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005471 /*
5472 * Check for illegal attributes.
5473 */
5474 attr = node->properties;
5475 while (attr != NULL) {
5476 if (attr->ns == NULL) {
5477 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5478 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5479 xmlSchemaPIllegalAttrErr(ctxt,
5480 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5481 NULL, type, attr);
5482 }
5483 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5484 xmlSchemaPIllegalAttrErr(ctxt,
5485 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5486 NULL, type, attr);
5487 }
5488 attr = attr->next;
5489 }
5490 /*
5491 * Attribute "itemType".
5492 */
5493 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5494 node, "itemType", &(type->baseNs), NULL, &(type->base));
5495 /*
5496 * And now for the children...
5497 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005498 child = node->children;
5499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005500 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5501 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005502 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005503 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005504 if (IS_SCHEMA(child, "simpleType")) {
5505 if (type->base != NULL) {
5506 xmlSchemaPCustomErr(ctxt,
5507 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5508 NULL, type, node,
5509 "The attribute 'itemType' and the <simpleType> child "
5510 "are mutually exclusive", NULL);
5511 } else {
5512 subtype = (xmlSchemaTypePtr)
5513 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5514 type->subtypes = subtype;
5515 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005516 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005517 }
5518 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005519 /* TODO: Think about the error code. */
5520 xmlSchemaPContentErr(ctxt,
5521 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5522 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005523 }
5524 return (type);
5525}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005526
Daniel Veillard4255d502002-04-16 15:50:10 +00005527/**
5528 * xmlSchemaParseSimpleType:
5529 * @ctxt: a schema validation context
5530 * @schema: the schema being built
5531 * @node: a subtree containing XML Schema informations
5532 *
5533 * parse a XML schema Simple Type definition
5534 * *WARNING* this interface is highly subject to change
5535 *
William M. Bracke7091952004-05-11 15:09:58 +00005536 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005537 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005538 */
5539static xmlSchemaTypePtr
5540xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005541 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005542{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005543 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005544 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005545 const xmlChar *attrValue = NULL;
5546 xmlChar *repName = NULL;
5547 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005548
5549 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5550 return (NULL);
5551
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005553
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 if (topLevel) {
5555 if (attr == NULL) {
5556 xmlSchemaPMissingAttrErr(ctxt,
5557 XML_SCHEMAP_S4S_ATTR_MISSING,
5558 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5559 "name", NULL);
5560 return (NULL);
5561 } else if (xmlSchemaPValAttrNode(ctxt,
5562 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5563 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005564 return (NULL);
5565 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005566 }
5567
5568 if (topLevel == 0) {
5569 char buf[100];
5570
Daniel Veillard01fa6152004-06-29 17:04:39 +00005571 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005572 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005573 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005574 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005575 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005576 if (type == NULL)
5577 return (NULL);
5578 type->node = node;
5579 type->type = XML_SCHEMA_TYPE_SIMPLE;
5580 /*
5581 * Check for illegal attributes.
5582 */
5583 attr = node->properties;
5584 while (attr != NULL) {
5585 if (attr->ns == NULL) {
5586 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5587 xmlSchemaPIllegalAttrErr(ctxt,
5588 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5589 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005590 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005591 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5592 xmlSchemaPIllegalAttrErr(ctxt,
5593 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5594 &repName, type, attr);
5595 }
5596 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005597 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 } else {
5599 /*
5600 * Parse as global simple type definition.
5601 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005602 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005603 if (type == NULL)
5604 return (NULL);
5605 type->node = node;
5606 type->type = XML_SCHEMA_TYPE_SIMPLE;
5607 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5608 /*
5609 * Check for illegal attributes.
5610 */
5611 attr = node->properties;
5612 while (attr != NULL) {
5613 if (attr->ns == NULL) {
5614 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5615 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5616 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5617 xmlSchemaPIllegalAttrErr(ctxt,
5618 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5619 &repName, type, attr);
5620 }
5621 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5622 xmlSchemaPIllegalAttrErr(ctxt,
5623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5624 &repName, type, attr);
5625 }
5626 attr = attr->next;
5627 }
5628 /*
5629 * Attribute "final".
5630 */
5631 attr = xmlSchemaGetPropNode(node, "final");
5632 if (attr == NULL) {
5633 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5634 } else {
5635 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5636 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5637 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5638 XML_SCHEMAS_TYPE_FINAL_LIST,
5639 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5640
5641 xmlSchemaPSimpleTypeErr(ctxt,
5642 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5643 &repName, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005644 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005645 attrValue, NULL, NULL, NULL);
5646 }
5647 }
5648 }
5649 /* TODO: Check id. */
5650 type->id = xmlSchemaGetProp(ctxt, node, "id");
5651 /*
5652 * And now for the children...
5653 */
5654 ctxtType = ctxt->ctxtType;
5655 ctxt->ctxtType = type;
5656 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005657 child = node->children;
5658 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005659 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5660 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005662 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005663 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005664 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005665 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005666 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005667 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005668 subtype = (xmlSchemaTypePtr)
5669 xmlSchemaParseList(ctxt, schema, child);
5670 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005672 subtype = (xmlSchemaTypePtr)
5673 xmlSchemaParseUnion(ctxt, schema, child);
5674 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005675 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005676 type->subtypes = subtype;
5677 if ((child != NULL) || (subtype == NULL)) {
5678 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5679 &repName, type, node, child, NULL,
5680 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005681 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005682 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 if (repName != NULL)
5684 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005685
Daniel Veillard4255d502002-04-16 15:50:10 +00005686 return (type);
5687}
5688
5689
5690/**
5691 * xmlSchemaParseGroup:
5692 * @ctxt: a schema validation context
5693 * @schema: the schema being built
5694 * @node: a subtree containing XML Schema informations
5695 *
5696 * parse a XML schema Group definition
5697 * *WARNING* this interface is highly subject to change
5698 *
William M. Bracke7091952004-05-11 15:09:58 +00005699 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005700 * 1 in case of success.
5701 */
5702static xmlSchemaTypePtr
5703xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005704 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005705{
5706 xmlSchemaTypePtr type, subtype;
5707 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005708 const xmlChar *name;
5709 const xmlChar *ref = NULL, *refNs = NULL;
5710 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00005711
5712 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5713 return (NULL);
5714
5715
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005716 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005717 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005718 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5719 if (ref == NULL) {
5720 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005721 XML_SCHEMAP_GROUP_NONAME_NOREF,
5722 "Group definition or particle: One of the attributes \"name\" "
5723 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005724 return (NULL);
5725 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005726 if (refNs == NULL)
5727 refNs = schema->targetNamespace;
5728 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5729 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005730 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005731 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005732 if (type == NULL)
5733 return (NULL);
5734 type->node = node;
5735 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005736 if (topLevel)
5737 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005738 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005739 type->ref = ref;
5740 type->refNs = refNs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005741
5742 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5743 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5744 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5745 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005746
5747 child = node->children;
5748 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005749 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5750 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005751 }
5752 subtype = NULL;
5753 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005754 subtype = (xmlSchemaTypePtr)
5755 xmlSchemaParseAll(ctxt, schema, child);
5756 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005758 subtype = xmlSchemaParseChoice(ctxt, schema, child);
5759 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005760 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005761 subtype = (xmlSchemaTypePtr)
5762 xmlSchemaParseSequence(ctxt, schema, child);
5763 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005764 }
5765 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005766 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005770 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005771 }
5772
5773 return (type);
5774}
5775
5776/**
5777 * xmlSchemaParseAll:
5778 * @ctxt: a schema validation context
5779 * @schema: the schema being built
5780 * @node: a subtree containing XML Schema informations
5781 *
5782 * parse a XML schema All definition
5783 * *WARNING* this interface is highly subject to change
5784 *
William M. Bracke7091952004-05-11 15:09:58 +00005785 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005786 * 1 in case of success.
5787 */
5788static xmlSchemaTypePtr
5789xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005790 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005791{
5792 xmlSchemaTypePtr type, subtype, last = NULL;
5793 xmlNodePtr child = NULL;
5794 xmlChar name[30];
5795
5796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5797 return (NULL);
5798
5799
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005801 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 if (type == NULL)
5803 return (NULL);
5804 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00005805 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005806 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005807
5808 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
5809 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Daniel Veillard4255d502002-04-16 15:50:10 +00005810
5811 child = node->children;
5812 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5814 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 }
5816 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005817 subtype = (xmlSchemaTypePtr)
5818 xmlSchemaParseElement(ctxt, schema, child, 0);
5819 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00005820 if (subtype->minOccurs > 1)
5821 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005822 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005823 NULL, NULL);
5824 if (subtype->maxOccurs > 1)
5825 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005826 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005827 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 if (last == NULL) {
5829 type->subtypes = subtype;
5830 last = subtype;
5831 } else {
5832 last->next = subtype;
5833 last = subtype;
5834 }
5835 last->next = NULL;
5836 }
5837 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005838 }
5839 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005840 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005841 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 }
5844
5845 return (type);
5846}
5847
5848/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005849 * xmlSchemaCleanupDoc:
5850 * @ctxt: a schema validation context
5851 * @node: the root of the document.
5852 *
5853 * removes unwanted nodes in a schemas document tree
5854 */
5855static void
5856xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
5857{
5858 xmlNodePtr delete, cur;
5859
5860 if ((ctxt == NULL) || (root == NULL)) return;
5861
5862 /*
5863 * Remove all the blank text nodes
5864 */
5865 delete = NULL;
5866 cur = root;
5867 while (cur != NULL) {
5868 if (delete != NULL) {
5869 xmlUnlinkNode(delete);
5870 xmlFreeNode(delete);
5871 delete = NULL;
5872 }
5873 if (cur->type == XML_TEXT_NODE) {
5874 if (IS_BLANK_NODE(cur)) {
5875 if (xmlNodeGetSpacePreserve(cur) != 1) {
5876 delete = cur;
5877 }
5878 }
5879 } else if ((cur->type != XML_ELEMENT_NODE) &&
5880 (cur->type != XML_CDATA_SECTION_NODE)) {
5881 delete = cur;
5882 goto skip_children;
5883 }
5884
5885 /*
5886 * Skip to next node
5887 */
5888 if (cur->children != NULL) {
5889 if ((cur->children->type != XML_ENTITY_DECL) &&
5890 (cur->children->type != XML_ENTITY_REF_NODE) &&
5891 (cur->children->type != XML_ENTITY_NODE)) {
5892 cur = cur->children;
5893 continue;
5894 }
5895 }
5896 skip_children:
5897 if (cur->next != NULL) {
5898 cur = cur->next;
5899 continue;
5900 }
5901
5902 do {
5903 cur = cur->parent;
5904 if (cur == NULL)
5905 break;
5906 if (cur == root) {
5907 cur = NULL;
5908 break;
5909 }
5910 if (cur->next != NULL) {
5911 cur = cur->next;
5912 break;
5913 }
5914 } while (cur != NULL);
5915 }
5916 if (delete != NULL) {
5917 xmlUnlinkNode(delete);
5918 xmlFreeNode(delete);
5919 delete = NULL;
5920 }
5921}
5922
William M. Brack2f2a6632004-08-20 23:09:47 +00005923
5924/**
5925 * xmlSchemaImportSchema
5926 *
5927 * @ctxt: a schema validation context
5928 * @schemaLocation: an URI defining where to find the imported schema
5929 *
5930 * import a XML schema
5931 * *WARNING* this interface is highly subject to change
5932 *
5933 * Returns -1 in case of error and 1 in case of success.
5934 */
5935#if 0
5936static xmlSchemaImportPtr
5937xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
5938 const xmlChar *schemaLocation)
5939{
5940 xmlSchemaImportPtr import;
5941 xmlSchemaParserCtxtPtr newctxt;
5942
5943 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5944 if (newctxt == NULL) {
5945 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
5946 NULL);
5947 return (NULL);
5948 }
5949 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
5950 /* Keep the same dictionnary for parsing, really */
5951 xmlDictReference(ctxt->dict);
5952 newctxt->dict = ctxt->dict;
5953 newctxt->includes = 0;
5954 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
5955
5956 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
5957 ctxt->userData);
5958
5959 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
5960 if (import == NULL) {
5961 xmlSchemaPErrMemory(NULL, "allocating imported schema",
5962 NULL);
5963 xmlSchemaFreeParserCtxt(newctxt);
5964 return (NULL);
5965 }
5966
5967 memset(import, 0, sizeof(xmlSchemaImport));
5968 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
5969 import->schema = xmlSchemaParse(newctxt);
5970
5971 if (import->schema == NULL) {
5972 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005973 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00005974 "Failed to import schema from location \"%s\".\n",
5975 schemaLocation, NULL);
5976
5977 xmlSchemaFreeParserCtxt(newctxt);
5978 /* The schemaLocation is held by the dictionary.
5979 if (import->schemaLocation != NULL)
5980 xmlFree((xmlChar *)import->schemaLocation);
5981 */
5982 xmlFree(import);
5983 return NULL;
5984 }
5985
5986 xmlSchemaFreeParserCtxt(newctxt);
5987 return import;
5988}
5989#endif
5990
5991static void
5992xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
5993{
5994 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5995 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
5996
5997 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5998 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
5999
6000 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6001 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6002 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6003 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6004 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6005 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6006 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6007 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6008
6009 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6010 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6011 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6012 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6013 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6014 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6015}
6016
6017static void
6018xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6019 xmlSchemaPtr schema,
6020 xmlNodePtr node)
6021{
6022 xmlAttrPtr attr;
6023 const xmlChar *val;
6024
6025 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6026 if (attr != NULL) {
6027 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6028 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6029 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6030 xmlSchemaPSimpleTypeErr(ctxt,
6031 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6032 NULL, NULL, (xmlNodePtr) attr, NULL,
6033 "(qualified | unqualified)", val, NULL, NULL, NULL);
6034 }
6035 }
6036
6037 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6038 if (attr != NULL) {
6039 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6040 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6041 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6042 xmlSchemaPSimpleTypeErr(ctxt,
6043 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6044 NULL, NULL, (xmlNodePtr) attr, NULL,
6045 "(qualified | unqualified)", val, NULL, NULL, NULL);
6046 }
6047 }
6048
6049 attr = xmlSchemaGetPropNode(node, "finalDefault");
6050 if (attr != NULL) {
6051 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6052 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6053 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6054 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6055 -1,
6056 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6057 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6058 xmlSchemaPSimpleTypeErr(ctxt,
6059 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6060 NULL, NULL, (xmlNodePtr) attr, NULL,
6061 "(#all | List of (extension | restriction | list | union))",
6062 val, NULL, NULL, NULL);
6063 }
6064 }
6065
6066 attr = xmlSchemaGetPropNode(node, "blockDefault");
6067 if (attr != NULL) {
6068 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6069 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6070 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6071 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6072 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6073 xmlSchemaPSimpleTypeErr(ctxt,
6074 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6075 NULL, NULL, (xmlNodePtr) attr, NULL,
6076 "(#all | List of (extension | restriction | substitution))",
6077 val, NULL, NULL, NULL);
6078 }
6079 }
6080}
6081
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006082/**
6083 * xmlSchemaParseSchemaTopLevel:
6084 * @ctxt: a schema validation context
6085 * @schema: the schemas
6086 * @nodes: the list of top level nodes
6087 *
6088 * Returns the internal XML Schema structure built from the resource or
6089 * NULL in case of error
6090 */
6091static void
6092xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6093 xmlSchemaPtr schema, xmlNodePtr nodes)
6094{
6095 xmlNodePtr child;
6096 xmlSchemaAnnotPtr annot;
6097
6098 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6099 return;
6100
6101 child = nodes;
6102 while ((IS_SCHEMA(child, "include")) ||
6103 (IS_SCHEMA(child, "import")) ||
6104 (IS_SCHEMA(child, "redefine")) ||
6105 (IS_SCHEMA(child, "annotation"))) {
6106 if (IS_SCHEMA(child, "annotation")) {
6107 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6108 if (schema->annot == NULL)
6109 schema->annot = annot;
6110 else
6111 xmlSchemaFreeAnnot(annot);
6112 } else if (IS_SCHEMA(child, "import")) {
6113 xmlSchemaParseImport(ctxt, schema, child);
6114 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006115 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006116 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006117 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006118 } else if (IS_SCHEMA(child, "redefine")) {
6119 TODO
6120 }
6121 child = child->next;
6122 }
6123 while (child != NULL) {
6124 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006125 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006126 child = child->next;
6127 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006128 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006129 child = child->next;
6130 } else if (IS_SCHEMA(child, "element")) {
6131 xmlSchemaParseElement(ctxt, schema, child, 1);
6132 child = child->next;
6133 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006134 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006135 child = child->next;
6136 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006137 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006138 child = child->next;
6139 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006140 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006141 child = child->next;
6142 } else if (IS_SCHEMA(child, "notation")) {
6143 xmlSchemaParseNotation(ctxt, schema, child);
6144 child = child->next;
6145 } else {
6146 xmlSchemaPErr2(ctxt, NULL, child,
6147 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006148 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006149 child->name, NULL);
6150 child = child->next;
6151 }
6152 while (IS_SCHEMA(child, "annotation")) {
6153 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6154 if (schema->annot == NULL)
6155 schema->annot = annot;
6156 else
6157 xmlSchemaFreeAnnot(annot);
6158 child = child->next;
6159 }
6160 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006161 ctxt->parentItem = NULL;
6162 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006163}
6164
William M. Brack2f2a6632004-08-20 23:09:47 +00006165
6166/**
6167 * xmlSchemaParseImport:
6168 * @ctxt: a schema validation context
6169 * @schema: the schema being built
6170 * @node: a subtree containing XML Schema informations
6171 *
6172 * parse a XML schema Import definition
6173 * *WARNING* this interface is highly subject to change
6174 *
6175 * Returns 0 in case of success, a positive error code if
6176 * not valid and -1 in case of an internal error.
6177 */
6178static int
6179xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6180 xmlNodePtr node)
6181{
6182 xmlNodePtr child = NULL;
6183 xmlSchemaImportPtr import = NULL;
6184 const xmlChar *namespace = NULL, *ns;
6185 const xmlChar *schemaLocation = NULL;
6186 const xmlChar *targetNamespace, *oldTNS, *url;
6187 xmlAttrPtr attr;
6188 xmlDocPtr doc;
6189 xmlNodePtr root;
6190 xmlChar *base = NULL;
6191 xmlChar *URI = NULL;
6192 int flags;
6193 xmlParserCtxtPtr parserCtxt;
6194
6195
6196 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6197 return (-1);
6198
6199 /*
6200 * Check for illegal attributes.
6201 */
6202 attr = node->properties;
6203 while (attr != NULL) {
6204 if (attr->ns == NULL) {
6205 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6206 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6207 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6208 xmlSchemaPIllegalAttrErr(ctxt,
6209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6210 NULL, NULL, attr);
6211 }
6212 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6213 xmlSchemaPIllegalAttrErr(ctxt,
6214 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6215 NULL, NULL, attr);
6216 }
6217 attr = attr->next;
6218 }
6219 /*
6220 * Extract and validate attributes.
6221 */
6222 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6223 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6224 &namespace) != 0) {
6225 xmlSchemaPSimpleTypeErr(ctxt,
6226 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6227 NULL, NULL, node,
6228 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6229 NULL, namespace, NULL, NULL, NULL);
6230 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6231 }
6232
6233 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6234 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6235 &schemaLocation) != 0) {
6236 xmlSchemaPSimpleTypeErr(ctxt,
6237 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6238 NULL, NULL, node,
6239 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6240 NULL, namespace, NULL, NULL, NULL);
6241 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6242 }
6243 /*
6244 * And now for the children...
6245 */
6246 child = node->children;
6247 if (IS_SCHEMA(child, "annotation")) {
6248 /*
6249 * the annotation here is simply discarded ...
6250 */
6251 child = child->next;
6252 }
6253 if (child != NULL) {
6254 xmlSchemaPContentErr(ctxt,
6255 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6256 NULL, NULL, node, child, NULL,
6257 "(annotation?)");
6258 }
6259 /*
6260 * Apply additional constraints.
6261 */
6262 if (namespace != NULL) {
6263 /*
6264 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6265 * must not match the ·actual value· of the enclosing <schema>'s
6266 * targetNamespace [attribute].
6267 */
6268 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6269 xmlSchemaPCustomErr(ctxt,
6270 XML_SCHEMAP_SRC_IMPORT_1_1,
6271 NULL, NULL, node,
6272 "The value of the attribute 'namespace' must not match "
6273 "the target namespace '%s' of the importing schema",
6274 schema->targetNamespace);
6275 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6276 }
6277 } else {
6278 /*
6279 * 1.2 If the namespace [attribute] is not present, then the enclosing
6280 * <schema> must have a targetNamespace [attribute].
6281 */
6282 if (schema->targetNamespace == NULL) {
6283 xmlSchemaPCustomErr(ctxt,
6284 XML_SCHEMAP_SRC_IMPORT_1_2,
6285 NULL, NULL, node,
6286 "The attribute 'namespace' must be existent if "
6287 "the importing schema has no target namespace",
6288 NULL);
6289 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6290 }
6291 }
6292
6293 /*
6294 * Given that the schemaLocation [attribute] is only a hint, it is open
6295 * to applications to ignore all but the first <import> for a given
6296 * namespace, regardless of the ·actual value· of schemaLocation, but
6297 * such a strategy risks missing useful information when new
6298 * schemaLocations are offered.
6299 *
6300 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6301 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6302 * valid or not.
6303 * We will follow XSV here.
6304 */
6305 if (schemaLocation == NULL) {
6306 /*
6307 * Schema Document Location Strategy:
6308 *
6309 * 3 Based on the namespace name, identify an existing schema document,
6310 * either as a resource which is an XML document or a <schema> element
6311 * information item, in some local schema repository;
6312 *
6313 * 5 Attempt to resolve the namespace name to locate such a resource.
6314 *
6315 * NOTE: Those stategies are not supported, so we will skip.
6316 */
6317 return (0);
6318 }
6319 if (namespace == NULL)
6320 ns = XML_SCHEMAS_NO_NAMESPACE;
6321 else
6322 ns = namespace;
6323
6324 import = xmlHashLookup(schema->schemasImports, ns);
6325 if (import != NULL) {
6326 /*
6327 * There was a valid resource for the specified namespace already
6328 * defined, so skip.
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006329 * TODO: This might be changed someday to allow import of
6330 * components from multiple documents for a single target namespace.
William M. Brack2f2a6632004-08-20 23:09:47 +00006331 */
6332 return (0);
6333 }
6334 /*
6335 * Schema Document Location Strategy:
6336 *
6337 * 2 Based on the location URI, identify an existing schema document,
6338 * either as a resource which is an XML document or a <schema> element
6339 * information item, in some local schema repository;
6340 *
6341 * 4 Attempt to resolve the location URI, to locate a resource on the
6342 * web which is or contains or references a <schema> element;
6343 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6344 *
6345 */
6346
6347 base = xmlNodeGetBase(node->doc, node);
6348 if (base == NULL) {
6349 URI = xmlBuildURI(schemaLocation, node->doc->URL);
6350 } else {
6351 URI = xmlBuildURI(schemaLocation, base);
6352 xmlFree(base);
6353 }
6354 if (URI != NULL) {
6355 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
6356 xmlFree(URI);
6357 }
6358
6359 parserCtxt = xmlNewParserCtxt();
6360 if (parserCtxt == NULL) {
6361 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6362 "allocating a parser context", NULL);
6363 return(-1);
6364 }
6365
6366 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
6367 NULL, SCHEMAS_PARSE_OPTIONS);
6368
6369 /*
6370 * 2.1 The referent is (a fragment of) a resource which is an
6371 * XML document (see clause 1.1), which in turn corresponds to
6372 * a <schema> element information item in a well-formed information
6373 * set, which in turn corresponds to a valid schema.
6374 * TODO: What to do with the "fragment" stuff?
6375 *
6376 * 2.2 The referent is a <schema> element information item in
6377 * a well-formed information set, which in turn corresponds
6378 * to a valid schema.
6379 * NOTE: 2.2 won't apply, since only XML documents will be processed
6380 * here.
6381 */
6382 if (doc == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006383 xmlErrorPtr lerr;
William M. Brack2f2a6632004-08-20 23:09:47 +00006384 /*
6385 * It is *not* an error for the application schema reference
6386 * strategy to fail.
6387 *
6388 * If the doc is NULL and the parser error is an IO error we
6389 * will assume that the resource could not be located or accessed.
6390 *
6391 * TODO: Try to find specific error codes to react only on
6392 * localisation failures.
6393 *
6394 * TODO, FIXME: Check the spec: is a namespace added to the imported
6395 * namespaces, even if the schemaLocation did not provide
6396 * a resource? I guess so, since omitting the "schemaLocation"
6397 * attribute, imports a namespace as well.
6398 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006399 lerr = xmlGetLastError();
6400 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006401 xmlFreeParserCtxt(parserCtxt);
6402 return(0);
6403 }
6404
6405 xmlSchemaPCustomErr(ctxt,
6406 XML_SCHEMAP_SRC_IMPORT_2_1,
6407 NULL, NULL, node,
6408 "Failed to parse the resource '%s' for import",
6409 schemaLocation);
6410 xmlFreeParserCtxt(parserCtxt);
6411 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6412 }
6413 xmlFreeParserCtxt(parserCtxt);
6414
6415 root = xmlDocGetRootElement(doc);
6416 if (root == NULL) {
6417 xmlSchemaPCustomErr(ctxt,
6418 XML_SCHEMAP_SRC_IMPORT_2_1,
6419 NULL, NULL, node,
6420 "The XML document '%s' to be imported has no document "
6421 "element", schemaLocation);
6422 xmlFreeDoc(doc);
6423 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6424 }
6425
6426 xmlSchemaCleanupDoc(ctxt, root);
6427
6428 if (!IS_SCHEMA(root, "schema")) {
6429 xmlSchemaPCustomErr(ctxt,
6430 XML_SCHEMAP_SRC_IMPORT_2_1,
6431 NULL, NULL, node,
6432 "The XML document '%s' to be imported is not a XML schema document",
6433 schemaLocation);
6434 xmlFreeDoc(doc);
6435 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6436 }
6437 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6438 /*
6439 * Schema Representation Constraint: Import Constraints and Semantics
6440 */
6441 if (namespace == NULL) {
6442 if (targetNamespace != NULL) {
6443 xmlSchemaPCustomErr(ctxt,
6444 XML_SCHEMAP_SRC_IMPORT_3_2,
6445 NULL, NULL, node,
6446 "No 'namespace' attribute was "
6447 "specified, thus the XML schema to be imported "
6448 "must have no target namespace", NULL);
6449 xmlFreeDoc(doc);
6450 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6451 }
6452 } else {
6453 if (targetNamespace == NULL) {
6454 xmlSchemaPCustomErr(ctxt,
6455 XML_SCHEMAP_SRC_IMPORT_3_1,
6456 NULL, NULL, node,
6457 "The attribute 'namespace' requires the XML schema to be "
6458 "imported to have a target namespace of '%s'", namespace);
6459 xmlFreeDoc(doc);
6460 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6461 } else if (!xmlStrEqual(targetNamespace, namespace)) {
6462 xmlSchemaPCustomErrExt(ctxt,
6463 XML_SCHEMAP_SRC_IMPORT_3_1,
6464 NULL, NULL, node,
6465 "The value '%s' of the attribute 'namespace' is not "
6466 "identical to the target namespace '%s' of the "
6467 "XML schema to be imported",
6468 namespace, targetNamespace, NULL);
6469 xmlFreeDoc(doc);
6470 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6471 }
6472 }
6473 /*
6474 * Finally, import the schema.
6475 */
6476 if (schema->schemasImports == NULL) {
6477 schema->schemasImports = xmlHashCreate(10);
6478 if (schema->schemasImports == NULL) {
6479 xmlSchemaPErr2(ctxt, node, child,
6480 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6481 "Internal error: failed to build import table.\n",
6482 NULL, NULL);
6483 return (-1);
6484 }
6485 }
6486 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6487 if (import == NULL) {
6488 xmlSchemaPErrMemory(NULL, "allocating imported schema", NULL);
6489 xmlFreeDoc(doc);
6490 return (-1);
6491 }
6492 memset(import, 0, sizeof(xmlSchemaImport));
6493 import->schemaLocation = schemaLocation;
6494 import->doc = doc;
6495 xmlHashAddEntry(schema->schemasImports, ns, import);
6496 /*
6497 * Save and reset the context & schema.
6498 */
6499 url = ctxt->URL;
6500 /* TODO: Check this. */
6501 ctxt->URL = schemaLocation;
6502 flags = schema->flags;
6503 oldTNS = schema->targetNamespace;
6504
6505 xmlSchemaClearSchemaDefaults(schema);
6506 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6507 schema->targetNamespace = targetNamespace;
6508 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6509
6510 /*
6511 * Restore the context & schema.
6512 */
6513 schema->flags = flags;
6514 schema->targetNamespace = oldTNS;
6515 ctxt->URL = url;
6516
6517 return (1);
6518}
6519
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006520/**
6521 * xmlSchemaParseInclude:
6522 * @ctxt: a schema validation context
6523 * @schema: the schema being built
6524 * @node: a subtree containing XML Schema informations
6525 *
6526 * parse a XML schema Include definition
6527 *
William M. Bracke7091952004-05-11 15:09:58 +00006528 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006529 * 1 in case of success.
6530 */
6531static int
6532xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6533 xmlNodePtr node)
6534{
6535 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006537 xmlDocPtr doc;
6538 xmlNodePtr root;
6539 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006541 xmlAttrPtr attr;
6542 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006543
6544
6545 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6546 return (-1);
6547
6548 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006549 * Check for illegal attributes.
6550 */
6551 attr = node->properties;
6552 while (attr != NULL) {
6553 if (attr->ns == NULL) {
6554 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6555 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6556 xmlSchemaPIllegalAttrErr(ctxt,
6557 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6558 NULL, NULL, attr);
6559 }
6560 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6561 xmlSchemaPIllegalAttrErr(ctxt,
6562 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6563 NULL, NULL, attr);
6564 }
6565 attr = attr->next;
6566 }
6567 /*
6568 * Extract and validate attributes.
6569 */
6570 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006571 * Preliminary step, extract the URI-Reference for the include and
6572 * make an URI from the base.
6573 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006574 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6575 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006576 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006577 xmlChar *uri = NULL;
6578
6579 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6580 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6581 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006582 base = xmlNodeGetBase(node->doc, node);
6583 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006584 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006585 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006586 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006587 xmlFree(base);
6588 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006589 if (uri != NULL) {
6590 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6591 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006592 }
6593 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006594 xmlSchemaPMissingAttrErr(ctxt,
6595 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6596 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006597 return (-1);
6598 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006599 /*
6600 * And now for the children...
6601 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006602 child = node->children;
6603 while (IS_SCHEMA(child, "annotation")) {
6604 /*
6605 * the annotations here are simply discarded ...
6606 */
6607 child = child->next;
6608 }
6609 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006610 xmlSchemaPContentErr(ctxt,
6611 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6612 NULL, NULL, node, child, NULL,
6613 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006614 }
6615
6616 /*
6617 * First step is to parse the input document into an DOM/Infoset
6618 */
6619 doc = xmlReadFile((const char *) schemaLocation, NULL,
6620 SCHEMAS_PARSE_OPTIONS);
6621 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006622 /*
6623 * TODO: It is not an error for the ·actual value· of the
6624 * schemaLocation [attribute] to fail to resolve it all, in which
6625 * case no corresponding inclusion is performed.
6626 * So do we need a warning report here?
6627 */
6628 xmlSchemaPCustomErr(ctxt,
6629 XML_SCHEMAP_FAILED_LOAD,
6630 NULL, NULL, node,
6631 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006632 return(-1);
6633 }
6634
6635 /*
6636 * Then extract the root of the schema
6637 */
6638 root = xmlDocGetRootElement(doc);
6639 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006640 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006641 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006642 NULL, NULL, node,
6643 "The included document '%s' has no document "
6644 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006645 xmlFreeDoc(doc);
6646 return (-1);
6647 }
6648
6649 /*
6650 * Remove all the blank text nodes
6651 */
6652 xmlSchemaCleanupDoc(ctxt, root);
6653
6654 /*
6655 * Check the schemas top level element
6656 */
6657 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006658 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006659 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006660 NULL, NULL, node,
6661 "The document '%s' to be included is not a schema document",
6662 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006663 xmlFreeDoc(doc);
6664 return (-1);
6665 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006666
William M. Brack2f2a6632004-08-20 23:09:47 +00006667 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006668 /*
6669 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6670 * value· is identical to the ·actual value· of the targetNamespace
6671 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6672 */
6673 if (targetNamespace != NULL) {
6674 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006675 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006676 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006677 NULL, NULL, node,
6678 "The target namespace of the included schema "
6679 "'%s' has to be absent, since the including schema "
6680 "has no target namespace",
6681 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006682 xmlFreeDoc(doc);
6683 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006684 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6685 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006686 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006687 NULL, NULL, node,
6688 "The target namespace '%s' of the included schema '%s' "
6689 "differs from '%s' of the including schema",
6690 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006691 xmlFreeDoc(doc);
6692 return (-1);
6693 }
6694 } else if (schema->targetNamespace != NULL) {
6695 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
6696 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
6697 } else
6698 wasConvertingNs = 1;
6699 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006700 /*
6701 * register the include
6702 */
6703 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
6704 if (include == NULL) {
6705 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
6706 xmlFreeDoc(doc);
6707 return (-1);
6708 }
6709
6710 memset(include, 0, sizeof(xmlSchemaInclude));
6711 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6712 include->doc = doc;
6713 include->next = schema->includes;
6714 schema->includes = include;
6715
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006716 /*
6717 * parse the declarations in the included file like if they
6718 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006719 */
6720 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006721 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006722 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006723 /*
6724 * The default values ("blockDefault", "elementFormDefault", etc.)
6725 * are set to the values of the included schema and restored afterwards.
6726 */
6727 saveFlags = schema->flags;
6728 xmlSchemaClearSchemaDefaults(schema);
6729 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006730 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00006731 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006732 /*
6733 * Remove the converting flag.
6734 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006735 if ((wasConvertingNs == 0) &&
6736 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006737 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006738 return (1);
6739}
6740
6741/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006742 * xmlSchemaParseChoice:
6743 * @ctxt: a schema validation context
6744 * @schema: the schema being built
6745 * @node: a subtree containing XML Schema informations
6746 *
6747 * parse a XML schema Choice definition
6748 * *WARNING* this interface is highly subject to change
6749 *
William M. Bracke7091952004-05-11 15:09:58 +00006750 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006751 * 1 in case of success.
6752 */
6753static xmlSchemaTypePtr
6754xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006755 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006756{
6757 xmlSchemaTypePtr type, subtype, last = NULL;
6758 xmlNodePtr child = NULL;
6759 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006760 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006761
6762 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6763 return (NULL);
6764
6765
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006766 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006767 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006768 if (type == NULL)
6769 return (NULL);
6770 type->node = node;
6771 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006772 /*
6773 * Check for illegal attributes.
6774 */
6775 attr = node->properties;
6776 while (attr != NULL) {
6777 if (attr->ns == NULL) {
6778 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6779 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6780 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6781 xmlSchemaPIllegalAttrErr(ctxt,
6782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6783 NULL, type, attr);
6784 }
6785 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6786 xmlSchemaPIllegalAttrErr(ctxt,
6787 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6788 NULL, type, attr);
6789 }
6790 attr = attr->next;
6791 }
6792 /*
6793 * Extract and validate attributes.
6794 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006795 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006796 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6797 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6798 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00006799 /*
6800 * And now for the children...
6801 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006802 child = node->children;
6803 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006804 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6805 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006806 }
6807 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006808 (IS_SCHEMA(child, "group")) ||
6809 (IS_SCHEMA(child, "any")) ||
6810 (IS_SCHEMA(child, "choice")) ||
6811 (IS_SCHEMA(child, "sequence"))) {
6812 subtype = NULL;
6813 if (IS_SCHEMA(child, "element")) {
6814 subtype = (xmlSchemaTypePtr)
6815 xmlSchemaParseElement(ctxt, schema, child, 0);
6816 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006817 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006818 } else if (IS_SCHEMA(child, "any")) {
6819 subtype = xmlSchemaParseAny(ctxt, schema, child);
6820 } else if (IS_SCHEMA(child, "sequence")) {
6821 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6822 } else if (IS_SCHEMA(child, "choice")) {
6823 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6824 }
6825 if (subtype != NULL) {
6826 if (last == NULL) {
6827 type->subtypes = subtype;
6828 last = subtype;
6829 } else {
6830 last->next = subtype;
6831 last = subtype;
6832 }
6833 last->next = NULL;
6834 }
6835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006836 }
6837 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006838 /* TODO: error code. */
6839 xmlSchemaPContentErr(ctxt,
6840 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
6841 NULL, type, node, child, NULL,
6842 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006843 }
6844
6845 return (type);
6846}
6847
6848/**
6849 * xmlSchemaParseSequence:
6850 * @ctxt: a schema validation context
6851 * @schema: the schema being built
6852 * @node: a subtree containing XML Schema informations
6853 *
6854 * parse a XML schema Sequence definition
6855 * *WARNING* this interface is highly subject to change
6856 *
William M. Bracke7091952004-05-11 15:09:58 +00006857 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006858 * 1 in case of success.
6859 */
6860static xmlSchemaTypePtr
6861xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006862 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006863{
6864 xmlSchemaTypePtr type, subtype, last = NULL;
6865 xmlNodePtr child = NULL;
6866 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006867 xmlAttrPtr attr;
6868 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006869
6870 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6871 return (NULL);
6872
William M. Brack2f2a6632004-08-20 23:09:47 +00006873 oldcontainer = ctxt->container;
6874 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
6875 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006876 if (type == NULL)
6877 return (NULL);
6878 type->node = node;
6879 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006880 /*
6881 * Check for illegal attributes.
6882 */
6883 attr = node->properties;
6884 while (attr != NULL) {
6885 if (attr->ns == NULL) {
6886 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6887 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6888 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6889 xmlSchemaPIllegalAttrErr(ctxt,
6890 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6891 NULL, type, attr);
6892 }
6893 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6894 xmlSchemaPIllegalAttrErr(ctxt,
6895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6896 NULL, type, attr);
6897 }
6898 attr = attr->next;
6899 }
6900 /*
6901 * Extract and validate attributes.
6902 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006903 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006904 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6905 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6906 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00006907 /*
6908 * And now for the children...
6909 */
6910 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006911 child = node->children;
6912 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006913 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6914 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006915 }
6916 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917 (IS_SCHEMA(child, "group")) ||
6918 (IS_SCHEMA(child, "any")) ||
6919 (IS_SCHEMA(child, "choice")) ||
6920 (IS_SCHEMA(child, "sequence"))) {
6921 subtype = NULL;
6922 if (IS_SCHEMA(child, "element")) {
6923 subtype = (xmlSchemaTypePtr)
6924 xmlSchemaParseElement(ctxt, schema, child, 0);
6925 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006926 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006927 } else if (IS_SCHEMA(child, "any")) {
6928 subtype = xmlSchemaParseAny(ctxt, schema, child);
6929 } else if (IS_SCHEMA(child, "choice")) {
6930 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6931 } else if (IS_SCHEMA(child, "sequence")) {
6932 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6933 }
6934 if (subtype != NULL) {
6935 if (last == NULL) {
6936 type->subtypes = subtype;
6937 last = subtype;
6938 } else {
6939 last->next = subtype;
6940 last = subtype;
6941 }
6942 last->next = NULL;
6943 }
6944 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006945 }
6946 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006947 xmlSchemaPContentErr(ctxt,
6948 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
6949 NULL, type, node, child, NULL,
6950 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006951 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006952 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006953
6954 return (type);
6955}
6956
6957/**
6958 * xmlSchemaParseRestriction:
6959 * @ctxt: a schema validation context
6960 * @schema: the schema being built
6961 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 *
6963 * parse a XML schema Restriction definition
6964 * *WARNING* this interface is highly subject to change
6965 *
6966 * Returns the type definition or NULL in case of error
6967 */
6968static xmlSchemaTypePtr
6969xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006970 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006971{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006972 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006973 xmlNodePtr child = NULL;
6974 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006975 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00006976 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006977
6978 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6979 return (NULL);
6980
6981 oldcontainer = ctxt->container;
6982
William M. Brack2f2a6632004-08-20 23:09:47 +00006983 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
6984 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006985 if (type == NULL)
6986 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006987 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006988 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006989 /*
6990 * Check for illegal attributes.
6991 */
6992 attr = node->properties;
6993 while (attr != NULL) {
6994 if (attr->ns == NULL) {
6995 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6996 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
6997 xmlSchemaPIllegalAttrErr(ctxt,
6998 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6999 NULL, type, attr);
7000 }
7001 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7002 xmlSchemaPIllegalAttrErr(ctxt,
7003 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7004 NULL, type, attr);
7005 }
7006 attr = attr->next;
7007 }
7008 /*
7009 * Extract and validate attributes.
7010 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007011 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007012 /*
7013 * Attribute "base".
7014 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007015 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007016 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007017 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7018 /* TODO: Think about the error code. */
7019 xmlSchemaPMissingAttrErr(ctxt,
7020 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7021 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007022 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007023 /*
7024 * And now for the children...
7025 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007026 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007027 child = node->children;
7028 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7030 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007031 }
7032 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007033 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7034 if (IS_SCHEMA(child, "all")) {
7035 subtype = (xmlSchemaTypePtr)
7036 xmlSchemaParseAll(ctxt, schema, child);
7037 child = child->next;
7038 type->subtypes = subtype;
7039 } else if (IS_SCHEMA(child, "choice")) {
7040 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7041 child = child->next;
7042 type->subtypes = subtype;
7043 } else if (IS_SCHEMA(child, "sequence")) {
7044 subtype = (xmlSchemaTypePtr)
7045 xmlSchemaParseSequence(ctxt, schema, child);
7046 child = child->next;
7047 type->subtypes = subtype;
7048 } else if (IS_SCHEMA(child, "group")) {
7049 subtype = (xmlSchemaTypePtr)
7050 xmlSchemaParseGroup(ctxt, schema, child, 0);
7051 child = child->next;
7052 type->subtypes = subtype;
7053 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007054 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7055 if (IS_SCHEMA(child, "simpleType")) {
7056 if (type->base != NULL) {
7057 /*
7058 * src-restriction-base-or-simpleType
7059 * Either the base [attribute] or the simpleType [child] of the
7060 * <restriction> element must be present, but not both.
7061 */
7062 xmlSchemaPContentErr(ctxt,
7063 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7064 NULL, NULL, type->node, child,
7065 "The attribute 'base' and the <simpleType> child are "
7066 "mutually exclusive", NULL);
7067 } else {
7068 subtype = (xmlSchemaTypePtr)
7069 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7070 type->baseType = subtype;
7071 }
7072 child = child->next;
7073 }
7074 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007075 if (IS_SCHEMA(child, "simpleType")) {
7076 subtype = (xmlSchemaTypePtr)
7077 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007078 type->subtypes = subtype;
7079 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007080 }
7081 }
7082 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7083 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7084 xmlSchemaFacetPtr facet, lastfacet = NULL;
7085
Daniel Veillard01fa6152004-06-29 17:04:39 +00007086 /*
7087 * Add the facets to the parent simpleType/complexType.
7088 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007089 /*
7090 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7091 * Simple Type Definition Schema Representation Constraint:
7092 * *Single Facet Value*
7093 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007094 while ((IS_SCHEMA(child, "minInclusive")) ||
7095 (IS_SCHEMA(child, "minExclusive")) ||
7096 (IS_SCHEMA(child, "maxInclusive")) ||
7097 (IS_SCHEMA(child, "maxExclusive")) ||
7098 (IS_SCHEMA(child, "totalDigits")) ||
7099 (IS_SCHEMA(child, "fractionDigits")) ||
7100 (IS_SCHEMA(child, "pattern")) ||
7101 (IS_SCHEMA(child, "enumeration")) ||
7102 (IS_SCHEMA(child, "whiteSpace")) ||
7103 (IS_SCHEMA(child, "length")) ||
7104 (IS_SCHEMA(child, "maxLength")) ||
7105 (IS_SCHEMA(child, "minLength"))) {
7106 facet = xmlSchemaParseFacet(ctxt, schema, child);
7107 if (facet != NULL) {
7108 if (lastfacet == NULL)
7109 ctxt->ctxtType->facets = facet;
7110 else
7111 lastfacet->next = facet;
7112 lastfacet = facet;
7113 lastfacet->next = NULL;
7114 }
7115 child = child->next;
7116 }
7117 /*
7118 * Create links for derivation and validation.
7119 */
7120 if (lastfacet != NULL) {
7121 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7122
7123 facet = ctxt->ctxtType->facets;
7124 do {
7125 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7126 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007127 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007128 xmlFree(facetLink);
7129 return (NULL);
7130 }
7131 facetLink->facet = facet;
7132 facetLink->next = NULL;
7133 if (lastFacetLink == NULL)
7134 ctxt->ctxtType->facetSet = facetLink;
7135 else
7136 lastFacetLink->next = facetLink;
7137 lastFacetLink = facetLink;
7138 facet = facet->next;
7139 } while (facet != NULL);
7140 }
7141 }
7142 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
William M. Brack2f2a6632004-08-20 23:09:47 +00007143 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007144 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007145 /* TODO: Think about the error code. */
7146 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7147 xmlSchemaPContentErr(ctxt,
7148 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7149 NULL, type, node, child, NULL,
7150 "annotation?, (group | all | choice | sequence)?, "
7151 "((attribute | attributeGroup)*, anyAttribute?))");
7152 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7153 xmlSchemaPContentErr(ctxt,
7154 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7155 NULL, type, node, child, NULL,
7156 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7157 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7158 "length | minLength | maxLength | enumeration | whiteSpace | "
7159 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7160 } else {
7161 /* Simple type */
7162 xmlSchemaPContentErr(ctxt,
7163 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7164 NULL, type, node, child, NULL,
7165 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7166 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7167 "length | minLength | maxLength | enumeration | whiteSpace | "
7168 "pattern)*))");
7169 }
7170 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007171 ctxt->container = oldcontainer;
7172 return (type);
7173}
7174
7175/**
7176 * xmlSchemaParseExtension:
7177 * @ctxt: a schema validation context
7178 * @schema: the schema being built
7179 * @node: a subtree containing XML Schema informations
7180 *
7181 * parse a XML schema Extension definition
7182 * *WARNING* this interface is highly subject to change
7183 *
7184 * Returns the type definition or NULL in case of error
7185 */
7186static xmlSchemaTypePtr
7187xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007188 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007189{
7190 xmlSchemaTypePtr type, subtype;
7191 xmlNodePtr child = NULL;
7192 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007193 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007194
7195 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7196 return (NULL);
7197
7198 oldcontainer = ctxt->container;
7199
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007200 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007201 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007202 if (type == NULL)
7203 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007204 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007205 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007206 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007207 ctxt->container = name;
7208
7209 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7210 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007211 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007212 "<extension>: The attribute \"base\" is missing.\n",
7213 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007214 }
7215 child = node->children;
7216 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007217 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7218 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007219 }
7220 subtype = NULL;
7221
7222 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007223 subtype = xmlSchemaParseAll(ctxt, schema, child);
7224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007225 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007226 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7227 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007228 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007229 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007231 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007232 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007234 }
7235 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007237 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7238 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007239 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007240 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7241 "<extension> has unexpected content.\n", type->name,
7242 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007243 }
7244 ctxt->container = oldcontainer;
7245 return (type);
7246}
7247
7248/**
7249 * xmlSchemaParseSimpleContent:
7250 * @ctxt: a schema validation context
7251 * @schema: the schema being built
7252 * @node: a subtree containing XML Schema informations
7253 *
7254 * parse a XML schema SimpleContent definition
7255 * *WARNING* this interface is highly subject to change
7256 *
7257 * Returns the type definition or NULL in case of error
7258 */
7259static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007260xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7261 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007262{
7263 xmlSchemaTypePtr type, subtype;
7264 xmlNodePtr child = NULL;
7265 xmlChar name[30];
7266
7267 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7268 return (NULL);
7269
William M. Bracke7091952004-05-11 15:09:58 +00007270 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007271 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007272 if (type == NULL)
7273 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007274 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007275 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007276 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007277
7278 child = node->children;
7279 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007280 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7281 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007282 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007283 ctxt->parentItem = type;
7284 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007285 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007286 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007287 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007288 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007289 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007290 subtype = (xmlSchemaTypePtr)
7291 xmlSchemaParseExtension(ctxt, schema, child);
7292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007293 }
7294 type->subtypes = subtype;
7295 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007296 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007297 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7298 "<simpleContent> has unexpected content.\n",
7299 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007300 }
7301 return (type);
7302}
7303
7304/**
7305 * xmlSchemaParseComplexContent:
7306 * @ctxt: a schema validation context
7307 * @schema: the schema being built
7308 * @node: a subtree containing XML Schema informations
7309 *
7310 * parse a XML schema ComplexContent definition
7311 * *WARNING* this interface is highly subject to change
7312 *
7313 * Returns the type definition or NULL in case of error
7314 */
7315static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007316xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7317 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007318{
7319 xmlSchemaTypePtr type, subtype;
7320 xmlNodePtr child = NULL;
7321 xmlChar name[30];
7322
7323 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7324 return (NULL);
7325
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007326 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007327 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007328 if (type == NULL)
7329 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007330 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007331 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007332 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007333
7334 child = node->children;
7335 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007336 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7337 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007338 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007339 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 subtype = NULL;
7341 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007342 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007343 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007344 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007345 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007346 subtype = (xmlSchemaTypePtr)
7347 xmlSchemaParseExtension(ctxt, schema, child);
7348 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007349 }
7350 type->subtypes = subtype;
7351 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007352 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007353 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
7354 "<complexContent> has unexpected content.\n",
7355 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 }
7357 return (type);
7358}
7359
7360/**
7361 * xmlSchemaParseComplexType:
7362 * @ctxt: a schema validation context
7363 * @schema: the schema being built
7364 * @node: a subtree containing XML Schema informations
7365 *
7366 * parse a XML schema Complex Type definition
7367 * *WARNING* this interface is highly subject to change
7368 *
7369 * Returns the type definition or NULL in case of error
7370 */
7371static xmlSchemaTypePtr
7372xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007373 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007374{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007375 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007376 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007377 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00007378 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007379 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00007380
7381 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7382 return (NULL);
7383
Daniel Veillard01fa6152004-06-29 17:04:39 +00007384 ctxtType = ctxt->ctxtType;
7385
Daniel Veillard4255d502002-04-16 15:50:10 +00007386 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007387 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007388 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007389 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007390 name = (const xmlChar *)buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00007391 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007392 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007393
William M. Bracke7091952004-05-11 15:09:58 +00007394 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
William M. Brack2f2a6632004-08-20 23:09:47 +00007395 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007396 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007397 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00007398 return (NULL);
7399 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007400 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00007401 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00007402
Daniel Veillard4255d502002-04-16 15:50:10 +00007403 type->node = node;
7404 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00007405 if (topLevel)
7406 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007407 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007408 ctxt->container = name;
7409
7410 child = node->children;
7411 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007412 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7413 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007414 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007415 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007416 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00007417 /* 3.4.3 : 2.2
7418 * Specifying mixed='true' when the <simpleContent>
7419 * alternative is chosen has no effect
7420 */
7421 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7422 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007423 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7424 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007425 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007426 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7427 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007428 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007429 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007430
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007431 if (IS_SCHEMA(child, "all")) {
7432 subtype = xmlSchemaParseAll(ctxt, schema, child);
7433 child = child->next;
7434 } else if (IS_SCHEMA(child, "choice")) {
7435 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7436 child = child->next;
7437 } else if (IS_SCHEMA(child, "sequence")) {
7438 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7439 child = child->next;
7440 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007441 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007442 child = child->next;
7443 }
7444 if (subtype != NULL)
7445 type->subtypes = subtype;
7446 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007447 }
7448 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007449 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007450 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
7451 "Complex type definition \"%s\" has unexpected content.\n",
7452 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007453 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007454 if (type->attributeWildcard != NULL)
7455 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00007456 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007457 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007458 return (type);
7459}
7460
Daniel Veillard4255d502002-04-16 15:50:10 +00007461/**
7462 * xmlSchemaParseSchema:
7463 * @ctxt: a schema validation context
7464 * @node: a subtree containing XML Schema informations
7465 *
7466 * parse a XML schema definition from a node set
7467 * *WARNING* this interface is highly subject to change
7468 *
7469 * Returns the internal XML Schema structure built from the resource or
7470 * NULL in case of error
7471 */
7472static xmlSchemaPtr
7473xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7474{
7475 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007476 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007477 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007478 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007479
7480 if ((ctxt == NULL) || (node == NULL))
7481 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007482
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007483 nberrors = ctxt->nberrors;
7484 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007485 if (IS_SCHEMA(node, "schema")) {
7486 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007487 if (schema == NULL)
7488 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007489 attr = xmlSchemaGetPropNode(node, "targetNamespace");
7490 if (attr != NULL) {
7491 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7492 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
7493 /*
7494 * TODO: Should we proceed with an invalid target namespace?
7495 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007496 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
7497 } else {
7498 schema->targetNamespace = NULL;
7499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007500 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007501 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007502 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7503 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7504
William M. Brack2f2a6632004-08-20 23:09:47 +00007505 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007506 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
7507 } else {
7508 xmlDocPtr doc;
7509
7510 doc = node->doc;
7511
7512 if ((doc != NULL) && (doc->URL != NULL)) {
7513 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7514 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007515 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007516 } else {
7517 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7518 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007520 }
7521 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007522 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007523 if (ctxt->nberrors != 0) {
7524 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007525 xmlSchemaFree(schema);
7526 schema = NULL;
7527 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007528 }
7529 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00007530#ifdef DEBUG
7531 if (schema == NULL)
7532 xmlGenericError(xmlGenericErrorContext,
7533 "xmlSchemaParse() failed\n");
7534#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007535 return (schema);
7536}
7537
7538/************************************************************************
7539 * *
7540 * Validating using Schemas *
7541 * *
7542 ************************************************************************/
7543
7544/************************************************************************
7545 * *
7546 * Reading/Writing Schemas *
7547 * *
7548 ************************************************************************/
7549
7550/**
7551 * xmlSchemaNewParserCtxt:
7552 * @URL: the location of the schema
7553 *
7554 * Create an XML Schemas parse context for that file/resource expected
7555 * to contain an XML Schemas file.
7556 *
7557 * Returns the parser context or NULL in case of error
7558 */
7559xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007560xmlSchemaNewParserCtxt(const char *URL)
7561{
Daniel Veillard4255d502002-04-16 15:50:10 +00007562 xmlSchemaParserCtxtPtr ret;
7563
7564 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007565 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007566
7567 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7568 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007570 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 return (NULL);
7572 }
7573 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007574 ret->dict = xmlDictCreate();
7575 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007576 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007577 return (ret);
7578}
7579
7580/**
Daniel Veillard6045c902002-10-09 21:13:59 +00007581 * xmlSchemaNewMemParserCtxt:
7582 * @buffer: a pointer to a char array containing the schemas
7583 * @size: the size of the array
7584 *
7585 * Create an XML Schemas parse context for that memory buffer expected
7586 * to contain an XML Schemas file.
7587 *
7588 * Returns the parser context or NULL in case of error
7589 */
7590xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007591xmlSchemaNewMemParserCtxt(const char *buffer, int size)
7592{
Daniel Veillard6045c902002-10-09 21:13:59 +00007593 xmlSchemaParserCtxtPtr ret;
7594
7595 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007596 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007597
7598 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7599 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007600 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007601 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007602 return (NULL);
7603 }
7604 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7605 ret->buffer = buffer;
7606 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007607 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00007608 return (ret);
7609}
7610
7611/**
Daniel Veillard9d751502003-10-29 13:21:47 +00007612 * xmlSchemaNewDocParserCtxt:
7613 * @doc: a preparsed document tree
7614 *
7615 * Create an XML Schemas parse context for that document.
7616 * NB. The document may be modified during the parsing process.
7617 *
7618 * Returns the parser context or NULL in case of error
7619 */
7620xmlSchemaParserCtxtPtr
7621xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
7622{
7623 xmlSchemaParserCtxtPtr ret;
7624
7625 if (doc == NULL)
7626 return (NULL);
7627
7628 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7629 if (ret == NULL) {
7630 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
7631 NULL);
7632 return (NULL);
7633 }
7634 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7635 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007636 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00007637 /* The application has responsibility for the document */
7638 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00007639
7640 return (ret);
7641}
7642
7643/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007644 * xmlSchemaFreeParserCtxt:
7645 * @ctxt: the schema parser context
7646 *
7647 * Free the resources associated to the schema parser context
7648 */
7649void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007650xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
7651{
Daniel Veillard4255d502002-04-16 15:50:10 +00007652 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007653 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007654 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007655 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007656 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00007657 xmlFree(ctxt);
7658}
7659
7660/************************************************************************
7661 * *
7662 * Building the content models *
7663 * *
7664 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007665
Daniel Veillard4255d502002-04-16 15:50:10 +00007666/**
7667 * xmlSchemaBuildAContentModel:
7668 * @type: the schema type definition
7669 * @ctxt: the schema parser context
7670 * @name: the element name whose content is being built
7671 *
7672 * Generate the automata sequence needed for that type
7673 */
7674static void
7675xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007676 xmlSchemaParserCtxtPtr ctxt,
7677 const xmlChar * name)
7678{
Daniel Veillard4255d502002-04-16 15:50:10 +00007679 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007680 xmlGenericError(xmlGenericErrorContext,
7681 "Found unexpected type = NULL in %s content model\n",
7682 name);
7683 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007684 }
7685 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 case XML_SCHEMA_TYPE_ANY: {
7687 xmlAutomataStatePtr start, end;
7688 xmlSchemaWildcardPtr wild;
7689 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00007690
Daniel Veillardc0826a72004-08-10 14:17:33 +00007691 wild = type->attributeWildcard;
7692
7693 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007694 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007695 "Internal error: xmlSchemaBuildAContentModel, "
7696 "no wildcard on xsd:any.\n", NULL, NULL);
7697 return;
7698 }
7699
7700 start = ctxt->state;
7701 end = xmlAutomataNewState(ctxt->am);
7702
7703 if (type->maxOccurs == 1) {
7704 if (wild->any == 1) {
7705 /*
7706 * We need to add both transitions:
7707 *
7708 * 1. the {"*", "*"} for elements in a namespace.
7709 */
7710 ctxt->state =
7711 xmlAutomataNewTransition2(ctxt->am,
7712 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7713 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7714 /*
7715 * 2. the {"*"} for elements in no namespace.
7716 */
7717 ctxt->state =
7718 xmlAutomataNewTransition2(ctxt->am,
7719 start, NULL, BAD_CAST "*", NULL, type);
7720 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7721
7722 } else if (wild->nsSet != NULL) {
7723 ns = wild->nsSet;
7724 do {
7725 ctxt->state = start;
7726 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7727 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
7728 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7729 ns = ns->next;
7730 } while (ns != NULL);
7731
7732 } else if (wild->negNsSet != NULL) {
7733 xmlAutomataStatePtr deadEnd;
7734
7735 deadEnd = xmlAutomataNewState(ctxt->am);
7736 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7737 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7738 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7739 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7740 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7741 }
7742 } else {
7743 int counter;
7744 xmlAutomataStatePtr hop;
7745 int maxOccurs =
7746 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
7747 int minOccurs =
7748 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
7749
7750 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
7751 hop = xmlAutomataNewState(ctxt->am);
7752 if (wild->any == 1) {
7753 ctxt->state =
7754 xmlAutomataNewTransition2(ctxt->am,
7755 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7756 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7757 ctxt->state =
7758 xmlAutomataNewTransition2(ctxt->am,
7759 start, NULL, BAD_CAST "*", NULL, type);
7760 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7761 } else if (wild->nsSet != NULL) {
7762 ns = wild->nsSet;
7763 do {
7764 ctxt->state =
7765 xmlAutomataNewTransition2(ctxt->am,
7766 start, NULL, BAD_CAST "*", ns->value, type);
7767 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7768 ns = ns->next;
7769 } while (ns != NULL);
7770
7771 } else if (wild->negNsSet != NULL) {
7772 xmlAutomataStatePtr deadEnd;
7773
7774 deadEnd = xmlAutomataNewState(ctxt->am);
7775 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7776 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7777 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7778 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7779 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7780 }
7781 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
7782 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
7783 }
7784 if (type->minOccurs == 0) {
7785 xmlAutomataNewEpsilon(ctxt->am, start, end);
7786 }
7787 ctxt->state = end;
7788 break;
7789 }
7790 case XML_SCHEMA_TYPE_ELEMENT:{
7791 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
7792
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007793 /* TODO : handle the namespace too */
7794 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007795
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 if (elem->maxOccurs >= UNBOUNDED) {
7797 if (elem->minOccurs > 1) {
7798 xmlAutomataStatePtr tmp;
7799 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007800
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007801 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7802 oldstate,
7803 NULL);
7804 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007806 counter = xmlAutomataNewCounter(ctxt->am,
7807 elem->minOccurs -
7808 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00007809
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007810 if (elem->refDecl != NULL) {
7811 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7812 elem->refDecl,
7813 ctxt,
7814 elem->refDecl->
7815 name);
7816 } else {
7817 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007818 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007819 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007820 elem->name,
7821 elem->targetNamespace,
7822 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007823 }
7824 tmp = ctxt->state;
7825 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7826 counter);
7827 ctxt->state =
7828 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7829 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00007830
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007831 } else {
7832 if (elem->refDecl != NULL) {
7833 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7834 elem->refDecl,
7835 ctxt,
7836 elem->refDecl->
7837 name);
7838 } else {
7839 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007840 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007841 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007842 elem->name,
7843 elem->targetNamespace,
7844 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007845 }
7846 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7847 oldstate);
7848 if (elem->minOccurs == 0) {
7849 /* basically an elem* */
7850 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7851 ctxt->state);
7852 }
7853 }
7854 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
7855 xmlAutomataStatePtr tmp;
7856 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007857
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007858 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7859 oldstate, NULL);
7860 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007861
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007862 counter = xmlAutomataNewCounter(ctxt->am,
7863 elem->minOccurs - 1,
7864 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007865
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007866 if (elem->refDecl != NULL) {
7867 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7868 elem->refDecl, ctxt,
7869 elem->refDecl->name);
7870 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007871 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007872 ctxt->state,
7873 NULL,
7874 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007875 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876 type);
7877 }
7878 tmp = ctxt->state;
7879 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7880 counter);
7881 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
7882 NULL,
7883 counter);
7884 if (elem->minOccurs == 0) {
7885 /* basically an elem? */
7886 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7887 ctxt->state);
7888 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00007889
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007890 } else {
7891 if (elem->refDecl != NULL) {
7892 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7893 elem->refDecl, ctxt,
7894 elem->refDecl->name);
7895 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007896 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007897 ctxt->state,
7898 NULL,
7899 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007900 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007901 type);
7902 }
7903 if (elem->minOccurs == 0) {
7904 /* basically an elem? */
7905 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7906 ctxt->state);
7907 }
7908 }
7909 break;
7910 }
7911 case XML_SCHEMA_TYPE_SEQUENCE:{
7912 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007914 /*
7915 * If max and min occurances are default (1) then
7916 * simply iterate over the subtypes
7917 */
7918 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
7919 subtypes = type->subtypes;
7920 while (subtypes != NULL) {
7921 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7922 subtypes = subtypes->next;
7923 }
7924 } else {
7925 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007926
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007927 if (type->maxOccurs >= UNBOUNDED) {
7928 if (type->minOccurs > 1) {
7929 xmlAutomataStatePtr tmp;
7930 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007931
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007932 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7933 oldstate,
7934 NULL);
7935 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007936
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007937 counter = xmlAutomataNewCounter(ctxt->am,
7938 type->
7939 minOccurs - 1,
7940 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007941
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 subtypes = type->subtypes;
7943 while (subtypes != NULL) {
7944 xmlSchemaBuildAContentModel(subtypes, ctxt,
7945 name);
7946 subtypes = subtypes->next;
7947 }
7948 tmp = ctxt->state;
7949 xmlAutomataNewCountedTrans(ctxt->am, tmp,
7950 oldstate, counter);
7951 ctxt->state =
7952 xmlAutomataNewCounterTrans(ctxt->am, tmp,
7953 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007954
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007955 } else {
7956 subtypes = type->subtypes;
7957 while (subtypes != NULL) {
7958 xmlSchemaBuildAContentModel(subtypes, ctxt,
7959 name);
7960 subtypes = subtypes->next;
7961 }
7962 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7963 oldstate);
7964 if (type->minOccurs == 0) {
7965 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7966 ctxt->state);
7967 }
7968 }
7969 } else if ((type->maxOccurs > 1)
7970 || (type->minOccurs > 1)) {
7971 xmlAutomataStatePtr tmp;
7972 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007973
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007974 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7975 oldstate,
7976 NULL);
7977 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00007978
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007979 counter = xmlAutomataNewCounter(ctxt->am,
7980 type->minOccurs -
7981 1,
7982 type->maxOccurs -
7983 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007984
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007985 subtypes = type->subtypes;
7986 while (subtypes != NULL) {
7987 xmlSchemaBuildAContentModel(subtypes, ctxt,
7988 name);
7989 subtypes = subtypes->next;
7990 }
7991 tmp = ctxt->state;
7992 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7993 counter);
7994 ctxt->state =
7995 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7996 counter);
7997 if (type->minOccurs == 0) {
7998 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7999 ctxt->state);
8000 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008001
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008002 } else {
8003 subtypes = type->subtypes;
8004 while (subtypes != NULL) {
8005 xmlSchemaBuildAContentModel(subtypes, ctxt,
8006 name);
8007 subtypes = subtypes->next;
8008 }
8009 if (type->minOccurs == 0) {
8010 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8011 ctxt->state);
8012 }
8013 }
8014 }
8015 break;
8016 }
8017 case XML_SCHEMA_TYPE_CHOICE:{
8018 xmlSchemaTypePtr subtypes;
8019 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008020
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008021 start = ctxt->state;
8022 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008023
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008024 /*
8025 * iterate over the subtypes and remerge the end with an
8026 * epsilon transition
8027 */
8028 if (type->maxOccurs == 1) {
8029 subtypes = type->subtypes;
8030 while (subtypes != NULL) {
8031 ctxt->state = start;
8032 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8033 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8034 subtypes = subtypes->next;
8035 }
8036 } else {
8037 int counter;
8038 xmlAutomataStatePtr hop;
8039 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8040 UNBOUNDED : type->maxOccurs - 1;
8041 int minOccurs =
8042 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008043
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008044 /*
8045 * use a counter to keep track of the number of transtions
8046 * which went through the choice.
8047 */
8048 counter =
8049 xmlAutomataNewCounter(ctxt->am, minOccurs,
8050 maxOccurs);
8051 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008052
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008053 subtypes = type->subtypes;
8054 while (subtypes != NULL) {
8055 ctxt->state = start;
8056 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8057 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8058 subtypes = subtypes->next;
8059 }
8060 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8061 counter);
8062 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8063 counter);
8064 }
8065 if (type->minOccurs == 0) {
8066 xmlAutomataNewEpsilon(ctxt->am, start, end);
8067 }
8068 ctxt->state = end;
8069 break;
8070 }
8071 case XML_SCHEMA_TYPE_ALL:{
8072 xmlAutomataStatePtr start;
8073 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008074
Daniel Veillard3646d642004-06-02 19:19:14 +00008075 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008076 int lax;
8077
8078 subtypes = type->subtypes;
8079 if (subtypes == NULL)
8080 break;
8081 start = ctxt->state;
8082 while (subtypes != NULL) {
8083 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008084 /*
8085 * the following 'if' was needed to fix bug 139897
8086 * not quite sure why it only needs to be done for
8087 * elements with a 'ref', but it seems to work ok.
8088 */
8089 if (subtypes->ref != NULL)
8090 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00008091 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008092 /* TODO : handle the namespace too */
8093 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
8094 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
8095 ctxt->state, elem->name, 1,
8096 1, subtypes);
8097 } else {
8098 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
8099 ctxt->state, elem->name,
8100 elem->minOccurs,
8101 elem->maxOccurs,
8102 subtypes);
8103 }
8104 subtypes = subtypes->next;
8105 }
8106 lax = type->minOccurs == 0;
8107 ctxt->state =
8108 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8109 lax);
8110 break;
8111 }
8112 case XML_SCHEMA_TYPE_RESTRICTION:
8113 if (type->subtypes != NULL)
8114 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8115 break;
8116 case XML_SCHEMA_TYPE_EXTENSION:
8117 if (type->baseType != NULL) {
8118 xmlSchemaTypePtr subtypes;
8119
Daniel Veillardf7627552004-04-22 07:15:40 +00008120 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008121 /* TODO: Change the error code. */
8122 xmlSchemaPCustomErr(ctxt,
8123 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8124 NULL, type, type->node,
8125 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008126 return;
8127 }
8128 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008129 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008130 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008131 subtypes = type->subtypes;
8132 while (subtypes != NULL) {
8133 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8134 subtypes = subtypes->next;
8135 }
8136 } else if (type->subtypes != NULL)
8137 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8138 break;
8139 case XML_SCHEMA_TYPE_GROUP:
8140 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00008141 xmlSchemaTypePtr rgroup;
8142 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008143 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00008144 type->refNs);
8145 if (rgroup == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008146 xmlSchemaPResCompAttrErr(ctxt,
8147 XML_SCHEMAP_SRC_RESOLVE,
8148 NULL, type, NULL,
8149 "ref", type->ref, type->refNs,
8150 XML_SCHEMA_TYPE_GROUP, NULL);
William M. Brack29aa7722004-05-12 00:27:56 +00008151 return;
8152 }
8153 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
8154 break;
8155 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008156 }
8157 case XML_SCHEMA_TYPE_COMPLEX:
8158 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8159 if (type->subtypes != NULL)
8160 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8161 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008162 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8163 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008164 default:
8165 xmlGenericError(xmlGenericErrorContext,
8166 "Found unexpected type %d in %s content model\n",
8167 type->type, name);
8168 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008169 }
8170}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008171
Daniel Veillard4255d502002-04-16 15:50:10 +00008172/**
8173 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008174 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00008175 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008176 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008177 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008178 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00008179 */
8180static void
8181xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 xmlSchemaParserCtxtPtr ctxt,
8183 const xmlChar * name)
8184{
Daniel Veillard4255d502002-04-16 15:50:10 +00008185 xmlAutomataStatePtr start;
8186
Daniel Veillard4255d502002-04-16 15:50:10 +00008187 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008188 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008189 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 elem->contentType = XML_SCHEMA_CONTENT_ANY;
8191 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008192 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008193 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008194 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008195 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8196 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008197 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008198
8199#ifdef DEBUG_CONTENT
8200 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008201 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008202#endif
8203
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 ctxt->am = xmlNewAutomata();
8205 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008206 xmlGenericError(xmlGenericErrorContext,
8207 "Cannot create automata for elem %s\n", name);
8208 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008209 }
8210 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
8211 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
8212 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00008213 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008214 if (elem->contModel == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008215 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 NULL, (xmlSchemaTypePtr) elem, NULL,
8217 "Failed to compile the content model", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008218 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008219 xmlSchemaPCustomErr(ctxt,
8220 XML_SCHEMAP_NOT_DETERMINISTIC,
8221 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008222 NULL, (xmlSchemaTypePtr) elem, NULL,
8223 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008224 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008225#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008226 xmlGenericError(xmlGenericErrorContext,
8227 "Content model of %s:\n", name);
8228 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008229#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008230 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008231 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008232 xmlFreeAutomata(ctxt->am);
8233 ctxt->am = NULL;
8234}
8235
8236/**
8237 * xmlSchemaRefFixupCallback:
8238 * @elem: the schema element context
8239 * @ctxt: the schema parser context
8240 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008241 * Resolves the references of an element declaration
8242 * or particle, which has an element declaration as it's
8243 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008244 */
8245static void
8246xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008247 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008248 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008249 const xmlChar * context ATTRIBUTE_UNUSED,
8250 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008251{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008252 if ((ctxt == NULL) || (elem == NULL) ||
8253 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008254 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008255 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008256 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008257 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008258
Daniel Veillardc0826a72004-08-10 14:17:33 +00008259 /*
8260 * TODO: Evaluate, what errors could occur if the declaration is not
8261 * found. It might be possible that the "typefixup" might crash if
8262 * no ref declaration was found.
8263 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008264 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008265 if (elemDecl == NULL) {
8266 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008267 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008268 NULL, (xmlSchemaTypePtr) elem, elem->node,
8269 "ref", elem->ref, elem->refNs,
8270 XML_SCHEMA_TYPE_ELEMENT, NULL);
8271 } else
8272 elem->refDecl = elemDecl;
8273 } else {
8274 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8275 xmlSchemaTypePtr type;
8276
8277 /* (type definition) ... otherwise the type definition ·resolved·
8278 * to by the ·actual value· of the type [attribute] ...
8279 */
8280 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8281 elem->namedTypeNs);
8282 if (type == NULL) {
8283 xmlSchemaPResCompAttrErr(ctxt,
8284 XML_SCHEMAP_SRC_RESOLVE,
8285 NULL, (xmlSchemaTypePtr) elem, elem->node,
8286 "type", elem->namedType, elem->namedTypeNs,
8287 XML_SCHEMA_TYPE_BASIC, "type definition");
8288 } else
8289 elem->subtypes = type;
8290 }
8291 if (elem->substGroup != NULL) {
8292 xmlSchemaElementPtr substHead;
8293
8294 /*
8295 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8296 * substitutionGroup?
8297 */
8298 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008299 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008300 if (substHead == NULL) {
8301 xmlSchemaPResCompAttrErr(ctxt,
8302 XML_SCHEMAP_SRC_RESOLVE,
8303 NULL, (xmlSchemaTypePtr) elem, NULL,
8304 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8305 XML_SCHEMA_TYPE_ELEMENT, NULL);
8306 } else {
8307 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8308 /*
8309 * (type definition)...otherwise the {type definition} of the
8310 * element declaration ·resolved· to by the ·actual value· of
8311 * the substitutionGroup [attribute], if present
8312 */
8313 if (elem->subtypes == NULL)
8314 elem->subtypes = substHead->subtypes;
8315 }
8316 }
8317 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8318 (elem->substGroup == NULL))
8319 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8320 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008321}
8322
William M. Bracke7091952004-05-11 15:09:58 +00008323/**
8324 * xmlSchemaParseListRefFixup:
8325 * @type: the schema type definition
8326 * @ctxt: the schema parser context
8327 *
8328 * Fixup of the itemType reference of the list type.
8329 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008330static void
William M. Bracke7091952004-05-11 15:09:58 +00008331xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008332{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008333
Daniel Veillard01fa6152004-06-29 17:04:39 +00008334 if (((type->base == NULL) &&
8335 (type->subtypes == NULL)) ||
8336 ((type->base != NULL) &&
8337 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008338 /*
8339 * src-list-itemType-or-simpleType
8340 * Either the itemType [attribute] or the <simpleType> [child] of
8341 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008342 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008343 /*
8344 * TODO: Move this to the parse function.
8345 */
8346 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008347 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008348 NULL, type, type->node,
8349 "The attribute 'itemType' and the <simpleType> child "
8350 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008351 } else if (type->base!= NULL) {
8352 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
8353 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008354 xmlSchemaPResCompAttrErr(ctxt,
8355 XML_SCHEMAP_SRC_RESOLVE,
8356 NULL, type, type->node,
8357 "itemType", type->base, type->baseNs,
8358 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008359 }
8360 }
8361 if ((type->subtypes != NULL) &&
8362 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8363 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008364}
8365
8366/**
8367 * xmlSchemaParseUnionRefCheck:
8368 * @typeDecl: the schema type definition
8369 * @ctxt: the schema parser context
8370 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00008371 * Checks and builds the memberTypes of the union type.
8372 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00008373 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008374static int
William M. Bracke7091952004-05-11 15:09:58 +00008375xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00008376 xmlSchemaParserCtxtPtr ctxt)
8377{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008378
Daniel Veillard01fa6152004-06-29 17:04:39 +00008379 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
8380 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00008381
Daniel Veillard01fa6152004-06-29 17:04:39 +00008382 /* 1 If the <union> alternative is chosen, then [Definition:]
8383 * define the explicit members as the type definitions ·resolved·
8384 * to by the items in the ·actual value· of the memberTypes [attribute],
8385 * if any, followed by the type definitions corresponding to the
8386 * <simpleType>s among the [children] of <union>, if any.
8387 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008388
Daniel Veillard01fa6152004-06-29 17:04:39 +00008389 if (type->type != XML_SCHEMA_TYPE_UNION)
8390 return (-1);
8391 if (ctxt->ctxtType == NULL) {
8392 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008393 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008394 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
8395 "available", NULL, NULL);
8396 return (-1);
8397 }
8398 /*
8399 * src-union-memberTypes-or-simpleTypes
8400 * Either the memberTypes [attribute] of the <union> element must
8401 * be non-empty or there must be at least one simpleType [child].
8402 */
8403 if ((type->base == NULL) &&
8404 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008405 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008406 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008407 NULL, NULL, type->node,
8408 "Either the attribute 'memberTypes' must be non-empty "
8409 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008410 }
8411
8412 ctxtType = ctxt->ctxtType;
8413 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008414 xmlAttrPtr attr;
8415 const xmlChar *cur, *end;
8416 xmlChar *tmp;
8417 const xmlChar *localName, *uri;
8418
8419 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00008420 cur = type->base;
8421 do {
8422 while (IS_BLANK_CH(*cur))
8423 cur++;
8424 end = cur;
8425 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8426 end++;
8427 if (end == cur)
8428 break;
8429 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008430 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
8431 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
8432 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008433 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008434 xmlSchemaPResCompAttrErr(ctxt,
8435 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
8436 NULL, NULL, type->node, "memberTypes", localName, uri,
8437 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008438 } else {
8439 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8440 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8441 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8442 if (link == NULL) {
8443 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8444 return (-1);
8445 }
8446 link->type = memberType;
8447 link->next = NULL;
8448 if (lastLink == NULL)
8449 ctxtType->memberTypes = link;
8450 else
8451 lastLink->next = link;
8452 lastLink = link;
8453 }
8454 xmlFree(tmp);
8455 cur = end;
8456 } while (*cur != 0);
8457 }
8458 /*
8459 * Add local simple types,
8460 */
8461 memberType = type->subtypes;
8462 while (memberType != NULL) {
8463 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8464 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8465 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8466 if (link == NULL) {
8467 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8468 return (-1);
8469 }
8470 link->type = memberType;
8471 link->next = NULL;
8472 if (lastLink == NULL)
8473 ctxtType->memberTypes = link;
8474 else
8475 lastLink->next = link;
8476 lastLink = link;
8477 memberType = memberType->next;
8478 }
8479 /*
8480 * The actual value is then formed by replacing any union type
8481 * definition in the ·explicit members· with the members of their
8482 * {member type definitions}, in order.
8483 */
8484 link = ctxtType->memberTypes;
8485 while (link != NULL) {
8486 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
8487 subLink = link->type->memberTypes;
8488 if (subLink != NULL) {
8489 link->type = subLink->type;
8490 if (subLink->next != NULL) {
8491 lastLink = link->next;
8492 subLink = subLink->next;
8493 prevLink = link;
8494 while (subLink != NULL) {
8495 newLink = (xmlSchemaTypeLinkPtr)
8496 xmlMalloc(sizeof(xmlSchemaTypeLink));
8497 if (newLink == NULL) {
8498 xmlSchemaPErrMemory(ctxt, "allocating a type link",
8499 NULL);
8500 return (-1);
8501 }
8502 newLink->type = memberType;
8503 prevLink->next = newLink;
8504 prevLink = newLink;
8505 newLink->next = lastLink;
8506
8507 subLink = subLink->next;
8508 }
8509 }
8510 }
8511 }
8512 link = link->next;
8513 }
8514
8515 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00008516}
8517
Daniel Veillard4255d502002-04-16 15:50:10 +00008518/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008519 * xmlSchemaIsDerivedFromBuiltInType:
8520 * @ctxt: the schema parser context
8521 * @type: the type definition
8522 * @valType: the value type
8523 *
8524 *
8525 * Returns 1 if the type has the given value type, or
8526 * is derived from such a type.
8527 */
William M. Brack803812b2004-06-03 02:11:24 +00008528static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008529xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
8530 xmlSchemaTypePtr type, int valType)
8531{
8532 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008533 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00008534 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008535 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00008536 return(1);
8537 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
8538 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
8539 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
8540 ((xmlSchemaAttributePtr) type)->subtypes, valType));
8541 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
8542 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
8543 if (type->baseType != NULL)
8544 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
8545 valType));
8546 } else if ((type->subtypes != NULL) &&
8547 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
8548 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
8549 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
8550 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
8551 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
8552 valType));
8553 }
8554
8555 return (0);
8556}
8557
8558/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00008559 * xmlSchemaIsDerivedFromBuiltInType:
8560 * @type: the simpleType definition
8561 *
8562 * Returns the primitive type of the given type or
8563 * NULL in case of error.
8564 */
8565static xmlSchemaTypePtr
8566xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
8567{
8568 while (type != NULL) {
8569 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
8570 return (type);
8571 type = type->baseType;
8572 }
8573
8574 return (NULL);
8575}
8576
8577
8578/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008579 * xmlSchemaBuildAttributeUsesOwned:
8580 * @ctxt: the schema parser context
8581 * @type: the complex type definition
8582 * @cur: the attribute declaration list
8583 * @lastUse: the top of the attribute use list
8584 *
8585 * Builds the attribute uses list on the given complex type.
8586 * This one is supposed to be called by
8587 * xmlSchemaBuildAttributeValidation only.
8588 */
8589static int
8590xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
8591 xmlSchemaAttributePtr cur,
8592 xmlSchemaAttributeLinkPtr *uses,
8593 xmlSchemaAttributeLinkPtr *lastUse)
8594{
8595 xmlSchemaAttributeLinkPtr tmp;
8596 while (cur != NULL) {
8597 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
8598 /*
8599 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
8600 * to by the ·actual value·s of the ref [attribute] of the
8601 * <attributeGroup> [children], if any."
8602 */
8603 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
8604 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
8605 lastUse) == -1) {
8606 return (-1);
8607 }
8608 } else {
8609 /* W3C: "1 The set of attribute uses corresponding to the
8610 * <attribute> [children], if any."
8611 */
8612 tmp = (xmlSchemaAttributeLinkPtr)
8613 xmlMalloc(sizeof(xmlSchemaAttributeLink));
8614 if (tmp == NULL) {
8615 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
8616 return (-1);
8617 }
8618 tmp->attr = cur;
8619 tmp->next = NULL;
8620 if (*uses == NULL)
8621 *uses = tmp;
8622 else
8623 (*lastUse)->next = tmp;
8624 *lastUse = tmp;
8625 }
8626 cur = cur->next;
8627 }
8628 return (0);
8629}
8630
Daniel Veillard50355f02004-06-08 17:52:16 +00008631/**
8632 * xmlSchemaCloneWildcardNsConstraints:
8633 * @ctxt: the schema parser context
8634 * @dest: the destination wildcard
8635 * @source: the source wildcard
8636 *
8637 * Clones the namespace constraints of source
8638 * and assignes them to dest.
8639 * Returns -1 on internal error, 0 otherwise.
8640 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008641static int
8642xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
8643 xmlSchemaWildcardPtr *dest,
8644 xmlSchemaWildcardPtr source)
8645{
8646 xmlSchemaWildcardNsPtr cur, tmp, last;
8647
8648 if ((source == NULL) || (*dest == NULL))
8649 return(-1);
8650 (*dest)->any = source->any;
8651 cur = source->nsSet;
8652 last = NULL;
8653 while (cur != NULL) {
8654 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8655 if (tmp == NULL)
8656 return(-1);
8657 tmp->value = cur->value;
8658 if (last == NULL)
8659 (*dest)->nsSet = tmp;
8660 else
8661 last->next = tmp;
8662 last = tmp;
8663 cur = cur->next;
8664 }
8665 if ((*dest)->negNsSet != NULL)
8666 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
8667 if (source->negNsSet != NULL) {
8668 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8669 if ((*dest)->negNsSet == NULL)
8670 return(-1);
8671 (*dest)->negNsSet->value = source->negNsSet->value;
8672 } else
8673 (*dest)->negNsSet = NULL;
8674 return(0);
8675}
8676
Daniel Veillard50355f02004-06-08 17:52:16 +00008677/**
8678 * xmlSchemaUnionWildcards:
8679 * @ctxt: the schema parser context
8680 * @completeWild: the first wildcard
8681 * @curWild: the second wildcard
8682 *
8683 * Unions the namespace constraints of the given wildcards.
8684 * @completeWild will hold the resulting union.
8685 * Returns a positive error code on failure, -1 in case of an
8686 * internal error, 0 otherwise.
8687 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008688static int
8689xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
8690 xmlSchemaWildcardPtr completeWild,
8691 xmlSchemaWildcardPtr curWild)
8692{
8693 xmlSchemaWildcardNsPtr cur, curB, tmp;
8694
8695 /*
8696 * 1 If O1 and O2 are the same value, then that value must be the
8697 * value.
8698 */
8699 if ((completeWild->any == curWild->any) &&
8700 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8701 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8702
8703 if ((completeWild->negNsSet == NULL) ||
8704 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8705
8706 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008707 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008708
8709 /*
8710 * Check equality of sets.
8711 */
8712 cur = completeWild->nsSet;
8713 while (cur != NULL) {
8714 found = 0;
8715 curB = curWild->nsSet;
8716 while (curB != NULL) {
8717 if (cur->value == curB->value) {
8718 found = 1;
8719 break;
8720 }
8721 curB = curB->next;
8722 }
8723 if (!found)
8724 break;
8725 cur = cur->next;
8726 }
8727 if (found)
8728 return(0);
8729 } else
8730 return(0);
8731 }
8732 }
8733 /*
8734 * 2 If either O1 or O2 is any, then any must be the value
8735 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008736 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008737 if (completeWild->any == 0) {
8738 completeWild->any = 1;
8739 if (completeWild->nsSet != NULL) {
8740 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8741 completeWild->nsSet = NULL;
8742 }
8743 if (completeWild->negNsSet != NULL) {
8744 xmlFree(completeWild->negNsSet);
8745 completeWild->negNsSet = NULL;
8746 }
8747 }
Daniel Veillard50355f02004-06-08 17:52:16 +00008748 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008749 }
8750 /*
8751 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
8752 * then the union of those sets must be the value.
8753 */
8754 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8755 int found;
8756 xmlSchemaWildcardNsPtr start;
8757
8758 cur = curWild->nsSet;
8759 start = completeWild->nsSet;
8760 while (cur != NULL) {
8761 found = 0;
8762 curB = start;
8763 while (curB != NULL) {
8764 if (cur->value == curB->value) {
8765 found = 1;
8766 break;
8767 }
8768 curB = curB->next;
8769 }
8770 if (!found) {
8771 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8772 if (tmp == NULL)
8773 return (-1);
8774 tmp->value = cur->value;
8775 tmp->next = completeWild->nsSet;
8776 completeWild->nsSet = tmp;
8777 }
8778 cur = cur->next;
8779 }
8780
8781 return(0);
8782 }
8783 /*
8784 * 4 If the two are negations of different values (namespace names
8785 * or ·absent·), then a pair of not and ·absent· must be the value.
8786 */
8787 if ((completeWild->negNsSet != NULL) &&
8788 (curWild->negNsSet != NULL) &&
8789 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
8790 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00008791
8792 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008793 }
8794 /*
8795 * 5.
8796 */
8797 if (((completeWild->negNsSet != NULL) &&
8798 (completeWild->negNsSet->value != NULL) &&
8799 (curWild->nsSet != NULL)) ||
8800 ((curWild->negNsSet != NULL) &&
8801 (curWild->negNsSet->value != NULL) &&
8802 (completeWild->nsSet != NULL))) {
8803
8804 int nsFound, absentFound = 0;
8805
8806 if (completeWild->nsSet != NULL) {
8807 cur = completeWild->nsSet;
8808 curB = curWild->negNsSet;
8809 } else {
8810 cur = curWild->nsSet;
8811 curB = completeWild->negNsSet;
8812 }
8813 nsFound = 0;
8814 while (cur != NULL) {
8815 if (cur->value == NULL)
8816 absentFound = 1;
8817 else if (cur->value == curB->value)
8818 nsFound = 1;
8819 if (nsFound && absentFound)
8820 break;
8821 cur = cur->next;
8822 }
8823
8824 if (nsFound && absentFound) {
8825 /*
8826 * 5.1 If the set S includes both the negated namespace
8827 * name and ·absent·, then any must be the value.
8828 */
8829 completeWild->any = 1;
8830 if (completeWild->nsSet != NULL) {
8831 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8832 completeWild->nsSet = NULL;
8833 }
8834 if (completeWild->negNsSet != NULL) {
8835 xmlFree(completeWild->negNsSet);
8836 completeWild->negNsSet = NULL;
8837 }
8838 } else if (nsFound && (!absentFound)) {
8839 /*
8840 * 5.2 If the set S includes the negated namespace name
8841 * but not ·absent·, then a pair of not and ·absent· must
8842 * be the value.
8843 */
8844 if (completeWild->nsSet != NULL) {
8845 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8846 completeWild->nsSet = NULL;
8847 }
8848 if (completeWild->negNsSet == NULL) {
8849 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8850 if (completeWild->negNsSet == NULL)
8851 return (-1);
8852 }
8853 completeWild->negNsSet->value = NULL;
8854 } else if ((!nsFound) && absentFound) {
8855 /*
8856 * 5.3 If the set S includes ·absent· but not the negated
8857 * namespace name, then the union is not expressible.
8858 */
8859 xmlSchemaPErr(ctxt, completeWild->node,
8860 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008861 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008862 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008863 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008864 } else if ((!nsFound) && (!absentFound)) {
8865 /*
8866 * 5.4 If the set S does not include either the negated namespace
8867 * name or ·absent·, then whichever of O1 or O2 is a pair of not
8868 * and a namespace name must be the value.
8869 */
8870 if (completeWild->negNsSet == NULL) {
8871 if (completeWild->nsSet != NULL) {
8872 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8873 completeWild->nsSet = NULL;
8874 }
8875 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8876 if (completeWild->negNsSet == NULL)
8877 return (-1);
8878 completeWild->negNsSet->value = curWild->negNsSet->value;
8879 }
8880 }
8881 return (0);
8882 }
8883 /*
8884 * 6.
8885 */
8886 if (((completeWild->negNsSet != NULL) &&
8887 (completeWild->negNsSet->value == NULL) &&
8888 (curWild->nsSet != NULL)) ||
8889 ((curWild->negNsSet != NULL) &&
8890 (curWild->negNsSet->value == NULL) &&
8891 (completeWild->nsSet != NULL))) {
8892
8893 if (completeWild->nsSet != NULL) {
8894 cur = completeWild->nsSet;
8895 } else {
8896 cur = curWild->nsSet;
8897 }
8898 while (cur != NULL) {
8899 if (cur->value == NULL) {
8900 /*
8901 * 6.1 If the set S includes ·absent·, then any must be the
8902 * value.
8903 */
8904 completeWild->any = 1;
8905 if (completeWild->nsSet != NULL) {
8906 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8907 completeWild->nsSet = NULL;
8908 }
8909 if (completeWild->negNsSet != NULL) {
8910 xmlFree(completeWild->negNsSet);
8911 completeWild->negNsSet = NULL;
8912 }
8913 return (0);
8914 }
8915 cur = cur->next;
8916 }
8917 if (completeWild->negNsSet == NULL) {
8918 /*
8919 * 6.2 If the set S does not include ·absent·, then a pair of not
8920 * and ·absent· must be the value.
8921 */
8922 if (completeWild->nsSet != NULL) {
8923 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8924 completeWild->nsSet = NULL;
8925 }
8926 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8927 if (completeWild->negNsSet == NULL)
8928 return (-1);
8929 completeWild->negNsSet->value = NULL;
8930 }
8931 return (0);
8932 }
8933 return (0);
8934
8935}
8936
Daniel Veillard50355f02004-06-08 17:52:16 +00008937/**
8938 * xmlSchemaIntersectWildcards:
8939 * @ctxt: the schema parser context
8940 * @completeWild: the first wildcard
8941 * @curWild: the second wildcard
8942 *
8943 * Intersects the namespace constraints of the given wildcards.
8944 * @completeWild will hold the resulting intersection.
8945 * Returns a positive error code on failure, -1 in case of an
8946 * internal error, 0 otherwise.
8947 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008948static int
8949xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
8950 xmlSchemaWildcardPtr completeWild,
8951 xmlSchemaWildcardPtr curWild)
8952{
William M. Brack803812b2004-06-03 02:11:24 +00008953 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008954
8955 /*
8956 * 1 If O1 and O2 are the same value, then that value must be the
8957 * value.
8958 */
8959 if ((completeWild->any == curWild->any) &&
8960 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8961 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8962
8963 if ((completeWild->negNsSet == NULL) ||
8964 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8965
8966 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008967 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008968
8969 /*
8970 * Check equality of sets.
8971 */
8972 cur = completeWild->nsSet;
8973 while (cur != NULL) {
8974 found = 0;
8975 curB = curWild->nsSet;
8976 while (curB != NULL) {
8977 if (cur->value == curB->value) {
8978 found = 1;
8979 break;
8980 }
8981 curB = curB->next;
8982 }
8983 if (!found)
8984 break;
8985 cur = cur->next;
8986 }
8987 if (found)
8988 return(0);
8989 } else
8990 return(0);
8991 }
8992 }
8993 /*
8994 * 2 If either O1 or O2 is any, then the other must be the value.
8995 */
8996 if ((completeWild->any != curWild->any) && (completeWild->any)) {
8997 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8998 return(-1);
8999 return(0);
9000 }
9001 /*
9002 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9003 * name or ·absent·) and the other is a set of (namespace names or
9004 * ·absent·), then that set, minus the negated value if it was in
9005 * the set, minus ·absent· if it was in the set, must be the value.
9006 */
9007 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9008 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9009 const xmlChar *neg;
9010
9011 if (completeWild->nsSet == NULL) {
9012 neg = completeWild->negNsSet->value;
9013 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9014 return(-1);
9015 } else
9016 neg = curWild->negNsSet->value;
9017 /*
9018 * Remove absent and negated.
9019 */
9020 prev = NULL;
9021 cur = completeWild->nsSet;
9022 while (cur != NULL) {
9023 if (cur->value == NULL) {
9024 if (prev == NULL)
9025 completeWild->nsSet = cur->next;
9026 else
9027 prev->next = cur->next;
9028 xmlFree(cur);
9029 break;
9030 }
9031 prev = cur;
9032 cur = cur->next;
9033 }
9034 if (neg != NULL) {
9035 prev = NULL;
9036 cur = completeWild->nsSet;
9037 while (cur != NULL) {
9038 if (cur->value == neg) {
9039 if (prev == NULL)
9040 completeWild->nsSet = cur->next;
9041 else
9042 prev->next = cur->next;
9043 xmlFree(cur);
9044 break;
9045 }
9046 prev = cur;
9047 cur = cur->next;
9048 }
9049 }
9050
9051 return(0);
9052 }
9053 /*
9054 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9055 * then the intersection of those sets must be the value.
9056 */
9057 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9058 int found;
9059
9060 cur = completeWild->nsSet;
9061 prev = NULL;
9062 while (cur != NULL) {
9063 found = 0;
9064 curB = curWild->nsSet;
9065 while (curB != NULL) {
9066 if (cur->value == curB->value) {
9067 found = 1;
9068 break;
9069 }
9070 curB = curB->next;
9071 }
9072 if (!found) {
9073 if (prev == NULL)
9074 completeWild->nsSet = cur->next;
9075 else
9076 prev->next = cur->next;
9077 tmp = cur->next;
9078 xmlFree(cur);
9079 cur = tmp;
9080 continue;
9081 }
9082 prev = cur;
9083 cur = cur->next;
9084 }
9085
9086 return(0);
9087 }
9088 /* 5 If the two are negations of different namespace names,
9089 * then the intersection is not expressible
9090 */
9091 if ((completeWild->negNsSet != NULL) &&
9092 (curWild->negNsSet != NULL) &&
9093 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9094 (completeWild->negNsSet->value != NULL) &&
9095 (curWild->negNsSet->value != NULL)) {
9096
9097 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009098 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009099 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009100 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009101 }
9102 /*
9103 * 6 If the one is a negation of a namespace name and the other
9104 * is a negation of ·absent·, then the one which is the negation
9105 * of a namespace name must be the value.
9106 */
9107 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9108 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9109 (completeWild->negNsSet->value == NULL)) {
9110 completeWild->negNsSet->value = curWild->negNsSet->value;
9111 }
9112 return(0);
9113}
9114
Daniel Veillard50355f02004-06-08 17:52:16 +00009115/**
9116 * xmlSchemaIsWildcardNsConstraintSubset:
9117 * @ctxt: the schema parser context
9118 * @wildA: the first wildcard
9119 * @wildB: the second wildcard
9120 *
9121 * Returns 1 if the namespace constraint of @wildA is an intensional
9122 * subset of @wildB, 0 otherwise.
9123 */
9124static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009125xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9126 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009127{
Daniel Veillard3646d642004-06-02 19:19:14 +00009128
Daniel Veillard50355f02004-06-08 17:52:16 +00009129 /*
9130 * Schema Component Constraint: Wildcard Subset
9131 */
9132 /*
9133 * 1 super must be any.
9134 */
9135 if (wildB->any)
9136 return (1);
9137 /*
9138 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9139 * 2.2 super must be a pair of not and the same value.
9140 */
9141 if ((wildA->negNsSet != NULL) &&
9142 (wildB->negNsSet != NULL) &&
9143 (wildA->negNsSet->value == wildA->negNsSet->value))
9144 return (1);
9145 /*
9146 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9147 */
9148 if (wildA->nsSet != NULL) {
9149 /*
9150 * 3.2.1 super must be the same set or a superset thereof.
9151 */
9152 if (wildB->nsSet != NULL) {
9153 xmlSchemaWildcardNsPtr cur, curB;
9154 int found = 0;
9155
9156 cur = wildA->nsSet;
9157 while (cur != NULL) {
9158 found = 0;
9159 curB = wildB->nsSet;
9160 while (curB != NULL) {
9161 if (cur->value == curB->value) {
9162 found = 1;
9163 break;
9164 }
9165 curB = curB->next;
9166 }
9167 if (!found)
9168 return (0);
9169 cur = cur->next;
9170 }
9171 if (found)
9172 return (1);
9173 } else if (wildB->negNsSet != NULL) {
9174 xmlSchemaWildcardNsPtr cur;
9175 /*
9176 * 3.2.2 super must be a pair of not and a namespace name or
9177 * ·absent· and that value must not be in sub's set.
9178 */
9179 cur = wildA->nsSet;
9180 while (cur != NULL) {
9181 if (cur->value == wildB->negNsSet->value)
9182 return (0);
9183 cur = cur->next;
9184 }
9185 return (1);
9186 }
9187 }
9188 return (0);
9189}
9190
9191/**
9192 * xmlSchemaBuildCompleteAttributeWildcard:
9193 * @ctxt: the schema parser context
9194 * @attrs: the attribute list
9195 * @completeWild: the resulting complete wildcard
9196 *
9197 * Returns -1 in case of an internal error, 0 otherwise.
9198 */
9199static int
9200xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9201 xmlSchemaAttributePtr attrs,
9202 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009203{
9204 while (attrs != NULL) {
9205 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9206 xmlSchemaAttributeGroupPtr group;
9207
9208 group = (xmlSchemaAttributeGroupPtr) attrs;
9209 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9210 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009211 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9212 group->attributes, &group->attributeWildcard) == -1)
9213 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009214 }
9215 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9216 }
9217 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009218 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009219 /*
9220 * Copy the first encountered wildcard as context, except for the annotation.
9221 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009222 *completeWild = xmlSchemaAddWildcard(ctxt);
9223 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9224 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9225 completeWild, group->attributeWildcard) == -1)
9226 return (-1);
9227 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009228 /*
9229 * Although the complete wildcard might not correspond to any
9230 * node in the schema, we will save this context node.
9231 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009232 (*completeWild)->node = group->attributeWildcard->node;
9233
9234 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9235 xmlSchemaFreeWildcard(*completeWild);
9236 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009237 }
9238 }
9239 }
9240 attrs = attrs->next;
9241 }
9242
Daniel Veillard50355f02004-06-08 17:52:16 +00009243 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009244}
9245
9246/**
9247 * xmlSchemaMatchesWildcardNs:
9248 * @wild: the wildcard
9249 * @ns: the namespace
9250 *
9251 *
9252 * Returns 1 if the given namespace matches the wildcard,
9253 * 0 otherwise.
9254 */
9255static int
9256xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9257{
9258 if (wild == NULL)
9259 return(0);
9260
9261 if (wild->any)
9262 return(1);
9263 else if (wild->nsSet != NULL) {
9264 xmlSchemaWildcardNsPtr cur;
9265
9266 cur = wild->nsSet;
9267 while (cur != NULL) {
9268 if (xmlStrEqual(cur->value, ns))
9269 return(1);
9270 cur = cur->next;
9271 }
9272 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9273 (!xmlStrEqual(wild->negNsSet->value, ns)))
9274 return(1);
9275
9276 return(0);
9277}
9278
9279/**
9280 * xmlSchemaBuildAttributeValidation:
9281 * @ctxt: the schema parser context
9282 * @type: the complex type definition
9283 *
9284 *
9285 * Builds the wildcard and the attribute uses on the given complex type.
9286 * Returns -1 if an internal error occurs, 0 otherwise.
9287 */
9288static int
9289xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
9290{
9291 xmlSchemaTypePtr baseType = NULL;
9292 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00009293 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009294 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009295 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00009296 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009297 xmlChar *str = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009298
Daniel Veillard01fa6152004-06-29 17:04:39 +00009299 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009300 /*
9301 * Complex Type Definition with complex content Schema Component.
9302 *
9303 * Attribute uses.
9304 */
9305 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009306 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009307 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00009308 "attribute uses already builded.\n",
9309 NULL, NULL);
9310 return (-1);
9311 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009312 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009313 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009314 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009315 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009316 type->name, NULL);
9317 return (-1);
9318 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009319 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009320 if (baseType == anyType)
9321 baseIsAnyType = 1;
9322 /*
9323 * Inherit the attribute uses of the base type.
9324 */
9325 /*
9326 * NOTE: It is allowed to "extend" the anyType complex type.
9327 */
9328 if (!baseIsAnyType) {
9329 if (baseType != NULL) {
9330 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
9331 tmp = (xmlSchemaAttributeLinkPtr)
9332 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9333 if (tmp == NULL) {
9334 xmlSchemaPErrMemory(ctxt,
9335 "building attribute uses of complexType", NULL);
9336 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009337 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009338 tmp->attr = cur->attr;
9339 tmp->next = NULL;
9340 if (type->attributeUses == NULL) {
9341 type->attributeUses = tmp;
9342 } else
9343 lastBaseUse->next = tmp;
9344 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009345 }
9346 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009347 }
9348 if ((type->subtypes != NULL) &&
9349 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9350 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9351 attrs = type->subtypes->subtypes->attributes;
9352 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
9353 } else {
9354 /* Short hand form of the complexType. */
9355 attrs = type->attributes;
9356 }
9357 /*
9358 * Handle attribute wildcards.
9359 */
9360 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9361 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009362 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009363 /* Either we used the short hand form... */
9364 ((type->subtypes == NULL) ||
9365 /* Or complexType -> restriction/extension */
9366 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00009367 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009368 return (-1);
9369 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009370 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009371 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
9372 * create the wildcard right from the start on the complexType,
9373 * rather than on the <restriction>/<extension>.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009374 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009375 if ((type->attributeWildcard != NULL) &&
9376 /* Either we used the short hand form... */
9377 ((type->subtypes == NULL) ||
9378 /* Or complexType -> restriction/extension */
9379 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
9380 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
9381
9382 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
9383 ((baseIsAnyType) ||
9384 ((baseType != NULL) &&
9385 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9386 (baseType->attributeWildcard != NULL)))) {
9387 if (type->attributeWildcard != NULL) {
9388 /*
9389 * Union the complete wildcard with the base wildcard.
9390 */
9391 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
9392 baseType->attributeWildcard) == -1)
9393 return (-1);
9394 } else {
9395 /*
9396 * Just inherit the wildcard.
9397 */
9398 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00009399 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009400 }
9401
9402 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9403 if (type->attributeWildcard != NULL) {
9404 /*
9405 * Derivation Valid (Restriction, Complex)
9406 * 4.1 The {base type definition} must also have one.
9407 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009408 if (baseType->attributeWildcard == NULL) {
9409 xmlSchemaPCustomErr(ctxt,
9410 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
9411 NULL, type, NULL,
9412 "The type has an attribute wildcard, "
9413 "but the base type %s does not have one",
9414 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9415 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009416 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009417 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009418 type->attributeWildcard, baseType->attributeWildcard) == 0) {
9419 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009420 xmlSchemaPCustomErr(ctxt,
9421 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
9422 NULL, type, NULL,
9423 "The attribute wildcard is not a valid "
9424 "subset of the wildcard in the base type %s",
9425 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9426 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009427 return (1);
9428 }
9429 /* 4.3 Unless the {base type definition} is the ·ur-type
9430 * definition·, the complex type definition's {attribute
9431 * wildcard}'s {process contents} must be identical to or
9432 * stronger than the {base type definition}'s {attribute
9433 * wildcard}'s {process contents}, where strict is stronger
9434 * than lax is stronger than skip.
9435 */
9436 if ((type->baseType != anyType) &&
9437 (type->attributeWildcard->processContents <
9438 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009439 xmlSchemaPCustomErr(ctxt,
9440 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
9441 NULL, type, NULL,
9442 "The 'process contents' of the attribute wildcard is weaker than "
9443 "the one in the base type %s",
9444 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9445 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009446 return (1);
9447 }
9448 }
9449 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9450 /*
9451 * Derivation Valid (Extension)
9452 * At this point the type and the base have both, either
9453 * no wildcard or a wildcard.
9454 */
9455 if ((baseType->attributeWildcard != NULL) &&
9456 (baseType->attributeWildcard != type->attributeWildcard)) {
9457 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009458 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009459 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009460 xmlSchemaPCustomErr(ctxt,
9461 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
9462 NULL, type, NULL,
9463 "The attribute wildcard is not a valid "
9464 "superset of the one in the base type %s",
9465 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9466 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009467 return (1);
9468 }
9469 }
9470 }
9471
Daniel Veillard3646d642004-06-02 19:19:14 +00009472 /*
9473 * Gather attribute uses defined by this type.
9474 */
9475 if (attrs != NULL) {
9476 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
9477 &uses, &lastUse) == -1) {
9478 return (-1);
9479 }
9480 }
9481 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
9482 * "Two distinct attribute declarations in the {attribute uses} must
9483 * not have identical {name}s and {target namespace}s."
9484 *
9485 * For "extension" this is done further down.
9486 */
9487 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
9488 cur = uses;
9489 while (cur != NULL) {
9490 tmp = cur->next;
9491 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009492 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9493 xmlSchemaGetAttrName(tmp->attr))) &&
9494 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9495 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
9496
9497 xmlSchemaPAttrUseErr(ctxt,
9498 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9499 NULL, type, NULL, cur->attr,
9500 "Duplicate attribute use %s specified",
9501 xmlSchemaFormatNsUriLocal(&str,
9502 xmlSchemaGetAttrTargetNsURI(tmp->attr),
9503 xmlSchemaGetAttrName(tmp->attr))
9504 );
9505 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009506 break;
9507 }
9508 tmp = tmp->next;
9509 }
9510 cur = cur->next;
9511 }
9512 }
9513 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9514 /*
9515 * Derive by restriction.
9516 */
9517 if (baseIsAnyType) {
9518 type->attributeUses = uses;
9519 } else {
9520 int found;
9521
9522 cur = uses;
9523 while (cur != NULL) {
9524 found = 0;
9525 base = type->attributeUses;
9526 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009527 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9528 xmlSchemaGetAttrName(base->attr)) &&
9529 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
9530 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009531
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009533 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
9534 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9535 /*
9536 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +00009537 */
9538 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00009539 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 NULL, type, NULL, cur->attr,
9541 "The 'optional' use is inconsistent with a matching "
9542 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009543 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
9544 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9545 /*
9546 * derivation-ok-restriction 3
9547 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009548 xmlSchemaPCustomErr(ctxt,
9549 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
9550 NULL, type, NULL,
9551 "A matching attribute use for the 'required' "
9552 "attribute use %s of the base type is missing",
9553 xmlSchemaFormatNsUriLocal(&str,
9554 xmlSchemaGetAttrTargetNsURI(base->attr),
9555 xmlSchemaGetAttrName(base->attr)));
9556 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009557 } else {
9558 /*
9559 * Override the attribute use.
9560 */
9561 base->attr = cur->attr;
9562 }
9563 /*
9564 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00009565 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00009566 */
9567 break;
9568 }
9569 base = base->next;
9570 }
9571
9572 if (!found) {
9573 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9574 /*
9575 * derivation-ok-restriction 2.2
9576 */
9577 if ((type->attributeWildcard != NULL) &&
9578 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
9579 cur->attr->targetNamespace))
9580 found = 1;
9581
9582 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009583 xmlSchemaPAttrUseErr(ctxt,
9584 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
9585 NULL, type, NULL, cur->attr,
9586 "Neither a matching attribute use, "
9587 "nor a matching wildcard in the base type does exist",
9588 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009589 } else {
9590 /*
9591 * Add the attribute use.
9592 *
9593 * Note that this may lead to funny derivation error reports, if
9594 * multiple equal attribute uses exist; but this is not
9595 * allowed anyway, and it will be reported beforehand.
9596 */
9597 tmp = cur;
9598 if (prev != NULL)
9599 prev->next = cur->next;
9600 else
9601 uses = cur->next;
9602 cur = cur->next;
9603 if (type->attributeUses == NULL) {
9604 type->attributeUses = tmp;
9605 } else
9606 lastBaseUse->next = tmp;
9607 lastBaseUse = tmp;
9608
9609 continue;
9610 }
9611 }
9612 }
9613 prev = cur;
9614 cur = cur->next;
9615 }
9616 if (uses != NULL)
9617 xmlSchemaFreeAttributeUseList(uses);
9618 }
9619 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9620 /*
9621 * The spec allows only appending, and not other kinds of extensions.
9622 *
9623 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
9624 */
9625 if (uses != NULL) {
9626 if (type->attributeUses == NULL) {
9627 type->attributeUses = uses;
9628 } else
9629 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009630 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009631 } else {
9632 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00009633 * Derive implicitely from the ur-type.
9634 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009635 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009636 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009637 /*
9638 * 3.4.6 -> Complex Type Definition Properties Correct
9639 */
9640 if (type->attributeUses != NULL) {
9641 cur = type->attributeUses;
9642 prev = NULL;
9643 while (cur != NULL) {
9644 /*
9645 * 4. Two distinct attribute declarations in the {attribute uses} must
9646 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00009647 *
Daniel Veillard3646d642004-06-02 19:19:14 +00009648 * Note that this was already done for "restriction" and types derived from
9649 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00009650 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009651 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9652 tmp = cur->next;
9653 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009654 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9655 xmlSchemaGetAttrName(tmp->attr))) &&
9656 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9657 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009658
Daniel Veillardc0826a72004-08-10 14:17:33 +00009659 xmlSchemaPAttrUseErr(ctxt,
9660 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9661 NULL, type, NULL, tmp->attr,
9662 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009663 break;
9664 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009665 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009666 }
9667 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009668 /*
9669 * 5. Two distinct attribute declarations in the {attribute uses} must
9670 * not have {type definition}s which are or are derived from ID.
9671 */
9672 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009673 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009674 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009675 xmlSchemaPAttrUseErr(ctxt,
9676 XML_SCHEMAP_CT_PROPS_CORRECT_5,
9677 NULL, type, NULL, cur->attr,
9678 "There must not exist more than one attribute use, "
9679 "declared of type 'ID' or derived from it",
9680 NULL);
9681 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +00009682 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009683 id = cur;
9684 }
9685 /*
9686 * Remove "prohibited" attribute uses. The reason this is done at this late
9687 * stage is to be able to catch dublicate attribute uses. So we had to keep
9688 * prohibited uses in the list as well.
9689 */
9690 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9691 tmp = cur;
9692 if (prev == NULL)
9693 type->attributeUses = cur->next;
9694 else
9695 prev->next = cur->next;
9696 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009697 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00009698 } else {
9699 prev = cur;
9700 cur = cur->next;
9701 }
9702 }
9703 }
9704 /*
9705 * TODO: This check should be removed if we are 100% sure of
9706 * the base type attribute uses already being built.
9707 */
9708 if ((baseType != NULL) && (!baseIsAnyType) &&
9709 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9710 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009711 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009712 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009713 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009714 baseType->name, NULL);
9715 }
9716 return (0);
9717}
9718
9719/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009720 * xmlSchemaTypeFinalContains:
9721 * @schema: the schema
9722 * @type: the type definition
9723 * @final: the final
9724 *
9725 * Evaluates if a type definition contains the given "final".
9726 * This does take "finalDefault" into account as well.
9727 *
9728 * Returns 1 if the type does containt the given "final",
9729 * 0 otherwise.
9730 */
9731static int
9732xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
9733{
9734 int tfinal = final, tflags = type->flags;
9735
9736 if (type == NULL)
9737 return (0);
9738 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
9739 switch (final) {
9740 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
9741 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9742 break;
9743 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
9744 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9745 break;
9746 case XML_SCHEMAS_TYPE_FINAL_LIST:
9747 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
9748 break;
9749 case XML_SCHEMAS_TYPE_FINAL_UNION:
9750 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
9751 break;
9752 }
9753 tflags = schema->flags;
9754 }
9755 if (tflags & tfinal)
9756 return (1);
9757 else
9758 return (0);
9759
9760}
9761
9762/**
9763 * xmlSchemaGetUnionSimpleTypeMemberTypes:
9764 * @type: the Union Simple Type
9765 *
9766 * Returns a list of member types of @type if existing,
9767 * returns NULL otherwise.
9768 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009769static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00009770xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
9771{
9772 while (type != NULL) {
9773 if (type->memberTypes != NULL)
9774 return (type->memberTypes);
9775 else
9776 type = type->baseType;
9777 }
9778 return (NULL);
9779}
9780
9781/**
9782 * xmlSchemaGetListSimpleTypeItemType:
9783 * @type: the simple type definition
9784 *
9785 * Returns the item type definition of the list simple type.
9786 */
9787static xmlSchemaTypePtr
9788xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
9789{
9790 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
9791 return (NULL);
9792 /*
9793 * Note: In libxml2, the built-in types do not reflect
9794 * the datatype hierarchy (yet?) - we have to treat them
9795 * in a special way.
9796 */
9797 if (type->type == XML_SCHEMA_TYPE_BASIC)
9798 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
9799 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
9800 /* 1 If the <list> alternative is chosen, then the type
9801 * definition ·resolved· to by the ·actual value· of the
9802 * itemType [attribute] of <list>, if present, otherwise
9803 * the type definition corresponding to the <simpleType>
9804 * among the [children] of <list>.
9805 */
9806 return (type->subtypes->subtypes);
9807 else {
9808 /* 2 If the <restriction> option is chosen, then the
9809 * {item type definition} of the {base type definition}.
9810 */
9811 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
9812 }
9813}
9814
9815/**
9816 * xmlSchemaCheckCOSSTDerivedOK:
9817 * @type: the derived simple type definition
9818 * @baseType: the base type definition
9819 *
9820 * Checks wheter @type can be validly
9821 * derived from @baseType.
9822 *
9823 * Returns 0 on success, an positive error code otherwise.
9824 */
9825static int
9826xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
9827 xmlSchemaTypePtr type,
9828 xmlSchemaTypePtr baseType,
9829 int subset)
9830{
9831 /*
9832 * Schema Component Constraint: Type Derivation OK (Simple)
9833 *
9834 *
9835 * 1 They are the same type definition.
9836 * TODO: The identy check might have to be more complex than this.
9837 */
9838 if (type == baseType)
9839 return (0);
9840 /*
9841 * 2.1 restriction is not in the subset, or in the {final}
9842 * of its own {base type definition};
9843 */
9844 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
9845 (xmlSchemaTypeFinalContains(schema,
9846 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
9847 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
9848 }
9849 /* 2.2 */
9850 if (type->baseType == baseType) {
9851 /*
9852 * 2.2.1 D's ·base type definition· is B.
9853 */
9854 return (0);
9855 }
9856 /*
9857 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
9858 * and is validly derived from B given the subset, as defined by this
9859 * constraint.
9860 */
9861 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
9862 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
9863 return (0);
9864 }
9865 /*
9866 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
9867 * definition·.
9868 */
9869 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
9870 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
9871 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
9872 return (0);
9873 }
9874 /*
9875 * 2.2.4 B's {variety} is union and D is validly derived from a type
9876 * definition in B's {member type definitions} given the subset, as
9877 * defined by this constraint.
9878 *
9879 * NOTE: This seems not to involve built-in types, since there is no
9880 * built-in Union Simple Type.
9881 */
9882 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9883 xmlSchemaTypeLinkPtr cur;
9884
9885 cur = baseType->memberTypes;
9886 while (cur != NULL) {
9887 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
9888 cur->type, subset) == 0)
9889 return (0);
9890 cur = cur->next;
9891 }
9892 }
9893
9894 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
9895}
9896
9897
9898/**
9899 * xmlSchemaCheckSTPropsCorrect:
9900 * @ctxt: the schema parser context
9901 * @type: the simple type definition
9902 *
9903 * Checks st-props-correct.
9904 *
9905 * Returns 0 if the properties are correct,
9906 * if not, a positive error code and -1 on internal
9907 * errors.
9908 */
9909static int
9910xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
9911 xmlSchemaTypePtr type)
9912{
9913 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
9914 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009915 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009916
Daniel Veillardc0826a72004-08-10 14:17:33 +00009917 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009918 /*
9919 * Schema Component Constraint: Simple Type Definition Properties Correct
9920 *
9921 * NOTE: This is somehow redundant, since we actually built a simple type
9922 * to have all the needed information; this acts as an self test.
9923 */
9924 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9925 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9926 /*
9927 * TODO: 1 The values of the properties of a simple type definition must be as
9928 * described in the property tableau in Datatype definition, modulo the
9929 * impact of Missing Sub-components (§5.3).
9930 */
9931 /* Base type: If the datatype has been ·derived· by ·restriction·
9932 * then the Simple Type Definition component from which it is ·derived·,
9933 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
9934 */
9935 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009936 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009937 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009938 NULL, type, NULL,
9939 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009940 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9941 }
9942 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
9943 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
9944 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009945 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009946 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009947 NULL, type, NULL,
9948 "The base type %s is not a simple type",
9949 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9950 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009951 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9952 }
9953 if ((baseType != anySimpleType) &&
9954 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009955 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009956 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009957 NULL, type, NULL,
9958 "A type, derived by list or union, must have"
9959 "the simple ur-type definition as base type, not %s",
9960 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9961 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009962 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9963 }
9964 /*
9965 * Variety: One of {atomic, list, union}.
9966 */
9967 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9968 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
9969 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009970 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009972 NULL, type, NULL,
9973 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009974 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9975 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009976 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009977
9978 /*
9979 * 2 All simple type definitions must be derived ultimately from the ·simple
9980 * ur-type definition (so· circular definitions are disallowed). That is, it
9981 * must be possible to reach a built-in primitive datatype or the ·simple
9982 * ur-type definition· by repeatedly following the {base type definition}.
9983 */
9984 baseType = type->baseType;
9985 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
9986 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9987 xmlSchemaTypeFixup(baseType, ctxt, NULL);
9988 if (baseType == anySimpleType)
9989 break;
9990 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009991 xmlSchemaPCustomErr(ctxt,
9992 XML_SCHEMAP_ST_PROPS_CORRECT_2,
9993 NULL, type, NULL,
9994 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009995 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
9996 }
9997 baseType = baseType->baseType;
9998 }
9999 /*
10000 * 3 The {final} of the {base type definition} must not contain restriction.
10001 */
10002 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10003 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010004 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010005 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010006 NULL, type, NULL,
10007 "The 'final' of its base type %s must not contain "
10008 "'restriction'",
10009 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10010 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010011 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10012 }
10013 return (0);
10014}
10015
10016/**
10017 * xmlSchemaCheckDerivationValidSimpleRestriction:
10018 * @ctxt: the schema parser context
10019 * @type: the simple type definition
10020 *
10021 * Checks if the given @type (simpleType) is derived
10022 * validly by restriction.
10023 *
10024 * Returns -1 on internal errors, 0 if the type is validly derived,
10025 * a positive error code otherwise.
10026 */
10027static int
10028xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010029 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010030{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010031 xmlChar *str = NULL;
10032
10033 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010034
10035 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10036 xmlSchemaPErr(ctxt, type->node,
10037 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010038 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10039 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010040 type->name, NULL);
10041 return (-1);
10042 }
10043
10044 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10045 xmlSchemaTypePtr primitive;
10046 /*
10047 * 1.1 The {base type definition} must be an atomic simple
10048 * type definition or a built-in primitive datatype.
10049 */
10050 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010051 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010052 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010053 NULL, type, NULL,
10054 "The base type %s is not an atomic simple type",
10055 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10056 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010057 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10058 }
10059 /* 1.2 The {final} of the {base type definition} must not contain
10060 * restriction.
10061 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010062 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010063 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10064 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010065 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010066 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010067 NULL, type, NULL,
10068 "The final of its base type %s must not contain 'restriction'",
10069 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10070 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010071 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10072 }
10073
10074 /*
10075 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10076 * type definition}, as specified in the appropriate subsection of 3.2
10077 * Primitive datatypes.
10078 */
10079 if (type->facets != NULL) {
10080 xmlSchemaFacetPtr facet;
10081 int ok = 1;
10082
10083 primitive = xmlSchemaGetPrimitiveType(type);
10084 if (primitive == NULL) {
10085 xmlSchemaPErr(ctxt, type->node,
10086 XML_ERR_INTERNAL_ERROR,
10087 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010088 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010089 type->name, NULL);
10090 return (-1);
10091 }
10092 facet = type->facets;
10093 do {
10094 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010095 ok = 0;
10096 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010097 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010098 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010099 }
10100 facet = facet->next;
10101 } while (facet != NULL);
10102 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010103 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010104 }
10105 /*
10106 * TODO: 1.3.2 (facet derivation)
10107 */
10108 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10109 xmlSchemaTypePtr itemType = NULL;
10110
10111 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10112 if (itemType == NULL) {
10113 xmlSchemaPErr(ctxt, type->node,
10114 XML_ERR_INTERNAL_ERROR,
10115 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010116 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010117 type->name, NULL);
10118 return (-1);
10119 }
10120 /*
10121 * 2.1 The {item type definition} must have a {variety} of atomic or
10122 * union (in which case all the {member type definitions}
10123 * must be atomic).
10124 */
10125 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10126 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010127 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010128 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010129 NULL, type, NULL,
10130 "The item type %s must have a variety of atomic or union",
10131 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10132 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010133 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10134 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10135 xmlSchemaTypeLinkPtr member;
10136
10137 member = itemType->memberTypes;
10138 while (member != NULL) {
10139 if ((member->type->flags &
10140 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010141 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010142 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010143 NULL, type, NULL,
10144 "The item type is a union type, but the "
10145 "member type %s of this item type is not atomic",
10146 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10147 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010148 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10149 }
10150 member = member->next;
10151 }
10152 }
10153
10154 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10155 xmlSchemaFacetPtr facet;
10156 /*
10157 * This is the case if we have: <simpleType><list ..
10158 */
10159 /*
10160 * 2.3.1
10161 * 2.3.1.1 The {final} of the {item type definition} must not
10162 * contain list.
10163 */
10164 if (xmlSchemaTypeFinalContains(ctxt->schema,
10165 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010166 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010167 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010168 NULL, type, NULL,
10169 "The final of its item type %s must not contain 'list'",
10170 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10171 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010172 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10173 }
10174 /*
10175 * 2.3.1.2 The {facets} must only contain the whiteSpace
10176 * facet component.
10177 */
10178 if (type->facets != NULL) {
10179 facet = type->facets;
10180 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010181 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10182 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010183 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010184 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010185 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10186 }
10187 facet = facet->next;
10188 } while (facet != NULL);
10189 }
10190 /*
10191 * TODO: Datatypes states:
10192 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10193 * whose ·lexical space· allows space (such as string or anyURI)or
10194 * a ·union· datatype any of whose {member type definitions}'s
10195 * ·lexical space· allows space.
10196 */
10197 } else {
10198 /*
10199 * This is the case if we have: <simpleType><restriction ...
10200 */
10201 /*
10202 * 2.3.2
10203 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10204 */
10205 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010206 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010207 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010208 NULL, type, NULL,
10209 "The base type %s must be a list type",
10210 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10211 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010212 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10213 }
10214 /*
10215 * 2.3.2.2 The {final} of the {base type definition} must not
10216 * contain restriction.
10217 */
10218 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10219 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010220 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010221 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010222 NULL, type, NULL,
10223 "The final of the base type %s must not contain 'restriction'",
10224 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10225 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010226 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10227 }
10228 /*
10229 * 2.3.2.3 The {item type definition} must be validly derived
10230 * from the {base type definition}'s {item type definition} given
10231 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10232 */
10233 {
10234 xmlSchemaTypePtr baseItemType;
10235
10236 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
10237 if (baseItemType == NULL) {
10238 xmlSchemaPErr(ctxt, type->node,
10239 XML_ERR_INTERNAL_ERROR,
10240 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010241 "List simple type '%s': Failed to "
10242 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010243 type->name, type->baseType->name);
10244 return (-1);
10245 }
10246 if ((itemType != baseItemType) &&
10247 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
10248 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010249 xmlChar *strBIT = NULL, *strBT = NULL;
10250 xmlSchemaPCustomErrExt(ctxt,
10251 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
10252 NULL, type, NULL,
10253 "The item type %s is not validly derived from the "
10254 "item type %s of the base type %s",
10255 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
10256 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
10257 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10258
10259 FREE_AND_NULL(str)
10260 FREE_AND_NULL(strBIT)
10261 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010262 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
10263 }
10264 }
10265
10266 if (type->facets != NULL) {
10267 xmlSchemaFacetPtr facet;
10268 int ok = 1;
10269 /*
10270 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
10271 * and enumeration facet components are allowed among the {facets}.
10272 */
10273 facet = type->facets;
10274 do {
10275 switch (facet->type) {
10276 case XML_SCHEMA_FACET_LENGTH:
10277 case XML_SCHEMA_FACET_MINLENGTH:
10278 case XML_SCHEMA_FACET_MAXLENGTH:
10279 case XML_SCHEMA_FACET_WHITESPACE:
10280 /*
10281 * TODO: 2.5.1.2 List datatypes
10282 * The value of ·whiteSpace· is fixed to the value collapse.
10283 */
10284 case XML_SCHEMA_FACET_PATTERN:
10285 case XML_SCHEMA_FACET_ENUMERATION:
10286 break;
10287 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010288 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010289 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010290 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010291 /*
10292 * We could return, but it's nicer to report all
10293 * invalid facets.
10294 */
10295 ok = 0;
10296 }
10297 }
10298 facet = facet->next;
10299 } while (facet != NULL);
10300 if (ok == 0)
10301 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
10302 /*
10303 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
10304 * is a facet of the same kind in the {facets} of the {base type
10305 * definition} (call this BF),then the DF's {value} must be a valid
10306 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
10307 */
10308 }
10309
10310
10311 }
10312 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10313 /*
10314 * 3.1 The {member type definitions} must all have {variety} of
10315 * atomic or list.
10316 */
10317 xmlSchemaTypeLinkPtr member;
10318
10319 member = type->memberTypes;
10320 while (member != NULL) {
10321 if (((member->type->flags &
10322 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10323 ((member->type->flags &
10324 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010325 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010326 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010327 NULL, type, NULL,
10328 "The member type %s is neither an atomic, nor a list type",
10329 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10330 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010331 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
10332 }
10333 member = member->next;
10334 }
10335 /*
10336 * 3.3.1 If the {base type definition} is the ·simple ur-type
10337 * definition·
10338 */
10339 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10340 /*
10341 * 3.3.1.1 All of the {member type definitions} must have a
10342 * {final} which does not contain union.
10343 */
10344 member = type->memberTypes;
10345 while (member != NULL) {
10346 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
10347 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010348 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010349 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010350 NULL, type, NULL,
10351 "The final of member type %s contains 'union'",
10352 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10353 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010354 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
10355 }
10356 member = member->next;
10357 }
10358 /*
10359 * 3.3.1.2 The {facets} must be empty.
10360 */
10361 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010362 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010363 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010364 NULL, type, NULL,
10365 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010366 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
10367 }
10368 } else {
10369 /*
10370 * 3.3.2.1 The {base type definition} must have a {variety} of union.
10371 */
10372 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010373 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010374 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010375 NULL, type, NULL,
10376 "The base type %s is not a union type",
10377 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10378 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010379 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
10380 }
10381 /*
10382 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
10383 */
10384 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10385 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010386 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010387 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010388 NULL, type, NULL,
10389 "The final of its base type %s must not contain 'restriction'",
10390 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10391 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010392 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
10393 }
10394 /*
10395 * 3.3.2.3 The {member type definitions}, in order, must be validly
10396 * derived from the corresponding type definitions in the {base
10397 * type definition}'s {member type definitions} given the empty set,
10398 * as defined in Type Derivation OK (Simple) (§3.14.6).
10399 */
10400 {
10401 xmlSchemaTypeLinkPtr baseMember;
10402
10403 /*
10404 * OPTIMIZE: if the type is restricting, it has no local defined
10405 * member types and inherits the member types of the base type;
10406 * thus a check for equality can be skipped.
10407 */
10408 /*
10409 * TODO: Even worse: I cannot see a scenario where a restricting
10410 * union simple type can have other member types as the member
10411 * types of it's base type. This check seems not necessary with
10412 * respect to the derivation process in libxml2.
10413 */
10414 if (type->memberTypes != NULL) {
10415 member = type->memberTypes;
10416 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
10417 if ((member == NULL) && (baseMember != NULL)) {
10418 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010419 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010420 "Internal error: "
10421 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010422 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010423 "of member types in the base type\n",
10424 type->name, NULL);
10425 }
10426 while (member != NULL) {
10427 if (baseMember == NULL) {
10428 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010429 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010430 "Internal error: "
10431 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010432 "(3.3.2.3), union simple type '%s', unequal number "
10433 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010434 type->name, NULL);
10435 }
10436 if ((member->type != baseMember->type) &&
10437 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
10438 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010439 xmlChar *strBMT = NULL, *strBT = NULL;
10440
10441 xmlSchemaPCustomErrExt(ctxt,
10442 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
10443 NULL, type, NULL,
10444 "The member type %s is not validly derived from its "
10445 "corresponding member type %s of the base type %s",
10446 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
10447 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
10448 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10449 FREE_AND_NULL(str)
10450 FREE_AND_NULL(strBMT)
10451 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010452 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
10453 }
10454 member = member->next;
10455 baseMember = baseMember->next;
10456 }
10457 }
10458 }
10459 /*
10460 * 3.3.2.4 Only pattern and enumeration facet components are
10461 * allowed among the {facets}.
10462 */
10463 if (type->facets != NULL) {
10464 xmlSchemaFacetPtr facet;
10465 int ok = 1;
10466
10467 facet = type->facets;
10468 do {
10469 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
10470 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010471 xmlSchemaPIllegalFacetListUnionErr(ctxt,
10472 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
10473 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010474 ok = 0;
10475 }
10476 facet = facet->next;
10477 } while (facet != NULL);
10478 if (ok == 0)
10479 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
10480
10481 }
10482 /*
10483 * TODO: 3.3.2.5 (facet derivation)
10484 */
10485 }
10486 }
10487
10488 return (0);
10489}
10490
10491/**
10492 * xmlSchemaCheckSRCSimpleType:
10493 * @ctxt: the schema parser context
10494 * @type: the simple type definition
10495 *
10496 * Checks crc-simple-type constraints.
10497 *
10498 * Returns 0 if the constraints are satisfied,
10499 * if not a positive error code and -1 on internal
10500 * errors.
10501 */
10502static int
10503xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
10504 xmlSchemaTypePtr type)
10505{
10506 /*
10507 * NOTE: src-simple-type 2-4 are redundant, since the checks
10508 * were are done for the corresponding <restriction>, <list> and <union>
10509 * elements, but W3C wants a <simpleType> error as well, so it gets one.
10510 * Maby this can be skipped in the future, if we get sure it's not needed.
10511 */
10512 if (type->subtypes == NULL) {
10513 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010514 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010515 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010516 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010517 type->name, NULL);
10518 return (-1);
10519 }
10520 /*
10521 * src-simple-type.1 The corresponding simple type definition, if any,
10522 * must satisfy the conditions set out in Constraints on Simple Type
10523 * Definition Schema Components (§3.14.6).
10524 */
10525 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
10526 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
10527 /*
10528 * TODO: Removed this, since it got annoying to get an
10529 * extra error report, if anything failed until now.
10530 * Enable this if needed.
10531 */
10532 /*
10533 xmlSchemaPErr(ctxt, type->node,
10534 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010535 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010536 "on simple type definitions.\n",
10537 type->name, NULL);
10538 */
10539 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
10540 }
10541
10542 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
10543 /*
10544 * src-simple-type.2 If the <restriction> alternative is chosen,
10545 * either it must have a base [attribute] or a <simpleType> among its
10546 * [children], but not both.
10547 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010548 /*
10549 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
10550 * NOTE: This was removed, since this will be already handled
10551 * in the parse function for <restriction>.
10552 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010553 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
10554 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
10555 * an itemType [attribute] or a <simpleType> among its [children],
10556 * but not both.
10557 * NOTE: baseType is set to the local simple type definiton,
10558 * if existent, at parse time. This is a hack and not nice.
10559 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010560 /*
10561 * TODO: Remove this, and add the check to the parse function of <list>.
10562 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010563 if (((type->subtypes->base == NULL) &&
10564 (type->baseType == NULL)) ||
10565 ((type->subtypes->base != NULL) &&
10566 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010567 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010568 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010569 NULL, type, NULL,
10570 "Either the attribute 'itemType' or the <simpleType> child "
10571 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010572 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
10573 }
10574
10575
10576 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
10577 xmlSchemaTypeLinkPtr member;
10578 xmlSchemaTypePtr ancestor, anySimpleType;
10579
10580 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10581
10582 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
10583 * the <union> alternative is chosen, there must not be any entries
10584 * in the memberTypes [attribute] at any depth which resolve to the
10585 * component corresponding to the <simpleType>.
10586 */
10587 member = type->memberTypes;
10588 while (member != NULL) {
10589 ancestor = member->type;
10590 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
10591 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10592 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
10593 if (ancestor == anySimpleType)
10594 break;
10595 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010596 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010597 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010598 NULL, type, NULL,
10599 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010600 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
10601 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10602 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000010603 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000010604 * type as item type, which in turn has a list ST as member
10605 * type, we will assume this here as well, since this check
10606 * was not yet performed.
10607 */
10608
10609 }
10610 ancestor = ancestor->baseType;
10611 }
10612 member = member->next;
10613 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010614 }
10615
10616 return (0);
10617}
10618
William M. Brack2f2a6632004-08-20 23:09:47 +000010619#if 0 /* Not yet used code for CT schema validation */
10620static int
10621xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
10622 const xmlChar * value,
10623 xmlSchemaTypePtr type,
10624 int fireErrors)
10625{
10626 int ret;
10627 /*
10628 * 3.14.4 Simple Type Definition Validation Rules
10629 * Validation Rule: String Valid
10630 */
10631 /*
10632 * 1 It is schema-valid with respect to that definition as defined
10633 * by Datatype Valid in [XML Schemas: Datatypes].
10634 */
10635 ctxt->type = type;
10636 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, fireErrors, 1, 1);
10637 return (ret);
10638 /*
10639 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
10640 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
10641 * the string must be a ·declared entity name·.
10642 */
10643 /*
10644 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
10645 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
10646 * then every whitespace-delimited substring of the string must be a ·declared
10647 * entity name·.
10648 */
10649 /*
10650 * 2.3 otherwise no further condition applies.
10651 */
10652
10653 return (0);
10654}
10655
10656
10657static int
10658xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr ctxt,
10659 xmlSchemaElementPtr elemDecl)
10660{
10661 xmlSchemaTypePtr typeDef;
10662 if (elemDecl->value == NULL)
10663 return (0);
10664 if (elemDecl->subtypes == NULL) {
10665 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010666 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010667 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
10668 "Internal error: xmlSchemaCheckCOSValidDefault, "
10669 "the element decl. '%s' has no type assigned", elemDecl->name);
10670 return (-1);
10671 }
10672 typeDef = elemDecl->subtypes;
10673 if ((typeDef->type == XML_SCHEMA_TYPE_SIMPLE) ||
10674 ((typeDef->type == XML_SCHEMA_TYPE_COMPLEX) &&
10675 ((typeDef->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10676 (typeDef->contentType == XML_SCHEMA_CONTENT_BASIC)))) {
10677 xmlSchemaValidCtxtPtr vctxt;
10678 xmlAttrPtr attr;
10679 int ret = 0;
10680 /*
10681 * 1 If the type definition is a simple type definition, then the string
10682 * must be ·valid· with respect to that definition as defined by String
10683 * Valid (§3.14.4).
10684 */
10685 /*
10686 * 2.2.1 If the {content type} is a simple type definition, then the
10687 * string must be ·valid· with respect to that simple type definition
10688 * as defined by String Valid (§3.14.4).
10689 */
10690 /*
10691 * TODO: ?
10692 */
10693
10694 vctxt = xmlSchemaNewValidCtxt(NULL);
10695 if (vctxt == NULL) {
10696 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010697 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010698 "Internal error: xmlSchemaCheckCOSValidDefault, "
10699 "creation of a new validation context failed.\n",
10700 NULL, NULL);
10701 return (-1);
10702 }
10703 /*
10704 * TODO: This won't work.
10705 */
10706 if (typeDef->type == XML_SCHEMA_TYPE_SIMPLE)
10707 ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0);
10708 if (ret > 0) {
10709 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10710 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10711 else
10712 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10713 if (ctxt != NULL) {
10714 xmlSchemaPSimpleTypeErr(ctxt,
10715 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10716 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10717 elemDecl->subtypes, NULL, elemDecl->value,
10718 NULL, NULL, NULL);
10719 return (ctxt->err);
10720 }
10721 ret = ctxt->err;
10722 } else if (ret < 0) {
10723 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010724 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010725 "Internal error: xmlSchemaCheckCOSValidDefault, "
10726 "while validating the default/fixed value.\n",
10727 NULL, NULL);
10728 }
10729 xmlSchemaFreeValidCtxt(vctxt);
10730 return (ret);
10731 } else {
10732 /*
10733 * Complex type.
10734 *
10735 * 2.1 its {content type} must be a simple type definition or mixed.
10736 */
10737 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10738 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC) &&
10739 (elemDecl->subtypes->contentType == XML_SCHEMA_CONTENT_MIXED)) {
10740 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10741 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
10742 "The content type must be a simple type definition or mixed.",
10743 NULL);
10744 return(ctxt->err);
10745 }
10746 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10747 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC)) {
10748 xmlSchemaValidCtxtPtr vctxt;
10749 xmlAttrPtr attr;
10750 int ret;
10751
10752 /* TODO: Avoid creation of a new context. */
10753 vctxt = xmlSchemaNewValidCtxt(NULL);
10754 if (vctxt == NULL) {
10755 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010756 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010757 "Internal error: xmlSchemaCheckCOSValidDefault, "
10758 "creation of a new validation context failed.\n",
10759 NULL, NULL);
10760 return (-1);
10761 }
10762 vctxt->type = elemDecl->subtypes;
10763 ret = xmlSchemaValidateSimpleTypeValue(vctxt, elemDecl->value, 0, 1, 1);
10764 if (ret > 0) {
10765 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10766 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10767 else
10768 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10769 if (ctxt != NULL) {
10770 xmlSchemaPSimpleTypeErr(ctxt,
10771 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10772 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10773 elemDecl->subtypes, NULL, elemDecl->value,
10774 NULL, NULL, NULL);
10775 return (ctxt->err);
10776 }
10777 ret = ctxt->err;
10778 } else if (ret < 0) {
10779 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010780 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010781 "Internal error: xmlSchemaCheckCOSValidDefault, "
10782 "while validating the default/fixed value.\n",
10783 NULL, NULL);
10784 }
10785 xmlSchemaFreeValidCtxt(vctxt);
10786 return (ret);
10787 } else {
10788 /*
10789 * 2.2.2 If the {content type} is mixed, then the {content type}'s
10790 * particle must be ·emptiable· as defined by Particle Emptiable
10791 * (§3.9.6).
10792 */
10793 /*
10794 * TODO: Implement this.
10795 */
10796 }
10797 }
10798
10799 return (0);
10800}
10801
10802/**
10803 * xmlSchemaGetSTContentOfCT:
10804 * @ctxt: the schema parser context
10805 * @type: the complex type definition
10806 *
10807 *
10808 * Returns the corresponding simple type for the content of
10809 * the complex type.
10810 */
10811static xmlSchemaTypePtr
10812xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
10813 xmlSchemaTypePtr type)
10814{
10815 xmlSchemaTypePtr orig = type, anyType;
10816
10817 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10818 while ((type != NULL) && (type != anyType) &&
10819 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10820 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
10821 return(type);
10822 type = type->baseType;
10823 }
10824 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010825 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010826 NULL, orig, NULL,
10827 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
10828 "no simple type for the content of complex type '%s' could be "
10829 "computed", orig->name);
10830 return (NULL);
10831}
10832
10833
10834static xmlSchemaTypePtr
10835xmlSchemaGetContentType(xmlSchemaParserCtxtPtr ctxt,
10836 xmlSchemaTypePtr type)
10837{
10838 if (type->baseType == NULL) {
10839 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010840 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010841 NULL, type, NULL,
10842 "Internal error: xmlSchemaGetContentType, "
10843 "the complex type '%s' has no base type", type->name);
10844 return (NULL);
10845 }
10846 if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
10847 if ((type->baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10848 ((type->baseType->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10849 (type->baseType->contentType == XML_SCHEMA_CONTENT_BASIC)) &&
10850 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
10851 /*
10852 * 1 If the type definition ·resolved· to by the ·actual value· of
10853 * the base [attribute] is a complex type definition whose own
10854 * {content type} is a simple type definition and the <restriction>
10855 * alternative is chosen
10856 */
10857
10858
10859 }
10860 } else {
10861
10862 }
10863}
10864
10865/**
10866 * xmlSchemaCheckCOSCTExtends:
10867 * @ctxt: the schema parser context
10868 * @type: the complex type definition
10869 *
10870 * Schema Component Constraint: Derivation Valid (Extension)
10871 *
10872 * Returns 0 if the constraints are satisfied, a positive
10873 * error code if not and -1 if an internal error occured.
10874 */
10875static int
10876xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
10877 xmlSchemaTypePtr type)
10878{
10879 xmlSchemaTypePtr base;
10880 /*
10881 * 1 If the {base type definition} is a complex type definition,
10882 * then all of the following must be true:
10883 */
10884 base = type->baseType;
10885 if (base == NULL) {
10886 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010887 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010888 NULL, type, NULL,
10889 "Internal error: xmlSchemaCheckCOSCTExtends, "
10890 "the complex type '%s' has no base type", type->name);
10891 return (-1);
10892 }
10893 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
10894 /*
10895 * 1.1 The {final} of the {base type definition} must not
10896 * contain extension.
10897 */
10898 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
10899 xmlSchemaPCustomErr(ctxt,
10900 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
10901 NULL, type, NULL,
10902 "The 'final' of the base type definition "
10903 "contains extension", NULL);
10904 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
10905 }
10906 /*
10907 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
10908 * of the complex type definition itself, that is, for every attribute
10909 * use in the {attribute uses} of the {base type definition}, there
10910 * must be an attribute use in the {attribute uses} of the complex
10911 * type definition itself whose {attribute declaration} has the same
10912 * {name}, {target namespace} and {type definition} as its attribute
10913 * declaration
10914 *
10915 * NOTE: This will be already satisfied by the way the attribute uses
10916 * are extended in xmlSchemaBuildAttributeValidation; thus this check
10917 * is not needed.
10918 */
10919
10920 /*
10921 * 1.3 If it has an {attribute wildcard}, the complex type definition
10922 * must also have one, and the base type definition's {attribute
10923 * wildcard}'s {namespace constraint} must be a subset of the complex
10924 * type definition's {attribute wildcard}'s {namespace constraint},
10925 * as defined by Wildcard Subset (§3.10.6).
10926 *
10927 * This is already checked in xmlSchemaBuildAttributeValidation; thus
10928 * this check is not needed.
10929 */
10930
10931 /*
10932 * 1.4 One of the following must be true:
10933 *
10934 * 1.4.1 The {content type} of the {base type definition} and the
10935 * {content type} of the complex type definition itself must be the same
10936 * simple type definition
10937 */
10938
10939
10940
10941 } else {
10942 /*
10943 * 2 If the {base type definition} is a simple type definition,
10944 * then all of the following must be true:
10945 */
10946 /*
10947 * 2.1 The {content type} must be the same simple type definition.
10948 */
10949 /*
10950 * 2.2 The {final} of the {base type definition} must not contain
10951 * extension
10952 */
10953 }
10954
10955}
10956
10957#endif
10958
Daniel Veillard01fa6152004-06-29 17:04:39 +000010959/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010960 * xmlSchemaTypeFixup:
10961 * @typeDecl: the schema type definition
10962 * @ctxt: the schema parser context
10963 *
10964 * Fixes the content model of the type.
10965 */
10966static void
10967xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010968 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000010969{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010970 xmlSchemaTypePtr ctxtType;
10971
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010972 if (typeDecl == NULL)
10973 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010974 /*
10975 * Do not allow the following types to be typefixed, prior to
10976 * the corresponding simple/complex types.
10977 */
10978 if (ctxt->ctxtType == NULL) {
10979 switch (typeDecl->type) {
10980 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10981 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10982 case XML_SCHEMA_TYPE_UNION:
10983 case XML_SCHEMA_TYPE_RESTRICTION:
10984 case XML_SCHEMA_TYPE_EXTENSION:
10985 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010986 default:
10987 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010988 }
10989 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010990 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010991 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010992 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010993 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010994 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
10995 if (typeDecl->subtypes != NULL) {
10996 if (typeDecl->subtypes->contentType ==
10997 XML_SCHEMA_CONTENT_UNKNOWN) {
10998 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
10999 NULL);
11000 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011001 typeDecl->contentType =
11002 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011003 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011004 break;
11005 }
11006 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011007 xmlSchemaTypePtr base = NULL;
11008
11009 ctxt->ctxtType->flags |=
11010 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
William M. Brack2f2a6632004-08-20 23:09:47 +000011011 if (typeDecl->baseType != NULL)
11012 base = typeDecl->baseType;
11013 else if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011014 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011015 xmlSchemaGetType(ctxt->schema, typeDecl->base,
11016 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011017 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011018 xmlSchemaPResCompAttrErr(ctxt,
11019 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000011020 NULL, NULL,
11021 (xmlNodePtr) xmlSchemaGetPropNode(typeDecl->node, "base"),
Daniel Veillardc0826a72004-08-10 14:17:33 +000011022 "base", typeDecl->base, typeDecl->baseNs,
11023 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011024 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000011025 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011026 xmlSchemaTypeFixup(base, ctxt, NULL);
11027 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011028 }
11029 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011030 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
11031 /*
11032 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000011033 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011034 /*
11035 * Content type.
11036 */
11037 if (typeDecl->subtypes == NULL)
11038 /* 1.1.1 */
11039 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11040 else if ((typeDecl->subtypes->subtypes == NULL) &&
11041 ((typeDecl->subtypes->type ==
11042 XML_SCHEMA_TYPE_ALL)
11043 || (typeDecl->subtypes->type ==
11044 XML_SCHEMA_TYPE_SEQUENCE)))
11045 /* 1.1.2 */
11046 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11047 else if ((typeDecl->subtypes->type ==
11048 XML_SCHEMA_TYPE_CHOICE)
11049 && (typeDecl->subtypes->subtypes == NULL))
11050 /* 1.1.3 */
11051 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11052 else {
11053 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011054 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011055 XML_SCHEMA_CONTENT_ELEMENTS;
11056 }
11057 } else {
11058 /*
11059 * SimpleType restriction.
11060 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011061 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011062 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011063 break;
11064 }
11065 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011066 xmlSchemaTypePtr base = NULL;
11067 xmlSchemaContentType explicitContentType;
11068
11069 /*
11070 * An extension does exist on a complexType only.
11071 */
11072 ctxt->ctxtType->flags |=
11073 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11074 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011075 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011076 xmlSchemaPCustomErr(ctxt,
11077 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
11078 NULL, typeDecl, typeDecl->node,
11079 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000011080 return;
11081 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011082 if (typeDecl->base != NULL) {
11083 base =
11084 xmlSchemaGetType(ctxt->schema, typeDecl->base,
11085 typeDecl->baseNs);
11086 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 xmlSchemaPResCompAttrErr(ctxt,
11088 XML_SCHEMAP_SRC_RESOLVE,
11089 NULL, typeDecl, typeDecl->node,
11090 "base", typeDecl->base, typeDecl->baseNs,
11091 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011092 } else if (base->contentType ==
11093 XML_SCHEMA_CONTENT_UNKNOWN) {
11094 typeDecl->recurse = 1;
11095 xmlSchemaTypeFixup(base, ctxt, NULL);
11096 typeDecl->recurse = 0;
11097 }
11098 /*
11099 * The type definition ·resolved· to by the ·actual
11100 * value· of the base [attribute]
11101 */
11102 ctxt->ctxtType->baseType = base;
11103 /*
11104 * TODO: This one is still needed for computation of
11105 * the content model by xmlSchemaBuildAContentModel.
11106 * Try to get rid of it.
11107 */
11108 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011109 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011110 if ((typeDecl->subtypes != NULL) &&
11111 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
11112 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
11113
11114 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
11115 if (typeDecl->subtypes == NULL)
11116 /* 1.1.1 */
11117 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11118 else if ((typeDecl->subtypes->subtypes == NULL) &&
11119 ((typeDecl->subtypes->type ==
11120 XML_SCHEMA_TYPE_ALL)
11121 || (typeDecl->subtypes->type ==
11122 XML_SCHEMA_TYPE_SEQUENCE)))
11123 /* 1.1.2 */
11124 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11125 else if ((typeDecl->subtypes->type ==
11126 XML_SCHEMA_TYPE_CHOICE)
11127 && (typeDecl->subtypes->subtypes == NULL))
11128 /* 1.1.3 */
11129 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11130 if (base != NULL) {
11131 /* It will be reported later, if the base is missing. */
11132 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
11133 /* 2.1 */
11134 typeDecl->contentType = base->contentType;
11135 } else if (base->contentType ==
11136 XML_SCHEMA_CONTENT_EMPTY) {
11137 /* 2.2 imbitable ! */
11138 typeDecl->contentType =
11139 XML_SCHEMA_CONTENT_ELEMENTS;
11140 } else {
11141 /* 2.3 imbitable pareil ! */
11142 typeDecl->contentType =
11143 XML_SCHEMA_CONTENT_ELEMENTS;
11144 }
11145 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011146 break;
11147 }
11148 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011149 ctxtType = ctxt->ctxtType;
11150 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011151 if ((typeDecl->subtypes == NULL) ||
11152 ((typeDecl->subtypes->type !=
11153 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
11154 (typeDecl->subtypes->type !=
11155 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
11156 /*
11157 * This case is understood as shorthand for complex
11158 * content restricting the ur-type definition, and
11159 * the details of the mappings should be modified as
11160 * necessary.
11161 */
11162 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11163 typeDecl->flags |=
11164 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11165 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011166 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011167 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011168 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11169 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011170 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011171 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011172 if ((typeDecl->subtypes != NULL) &&
11173 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011174 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011175 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011176 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011177 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011178 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011179 typeDecl->contentType =
11180 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011181 } else {
11182 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011183 typeDecl->contentType =
11184 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011185 }
11186 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011187 }
11188 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011189 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 break;
11191 }
11192 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
11193 if (typeDecl->subtypes == NULL) {
11194 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011195 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11196 typeDecl->contentType =
11197 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011198 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011199 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011200 typeDecl->contentType =
11201 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000011202 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
11204 NULL);
11205 if (typeDecl->subtypes != NULL)
11206 typeDecl->contentType =
11207 typeDecl->subtypes->contentType;
11208 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011209 /*
11210 * Removed due to implementation of the build of attribute uses.
11211 */
11212 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011213 if (typeDecl->attributes == NULL)
11214 typeDecl->attributes =
11215 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011216 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011217 }
11218 break;
11219 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011220 case XML_SCHEMA_TYPE_SIMPLE:
11221 /*
11222 * Simple Type Definition Schema Component
11223 *
11224 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011225 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011226 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11227 if (typeDecl->subtypes->contentType ==
11228 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011229 ctxt->ctxtType = typeDecl;
11230 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011231 }
11232 /* Fixup base type */
11233 if ((typeDecl->baseType != NULL) &&
11234 (typeDecl->baseType->contentType ==
11235 XML_SCHEMA_CONTENT_UNKNOWN)) {
11236 /* OPTIMIZE: Actually this one will never by hit, since
11237 * the base type is already type-fixed in <restriction>.
11238 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011239 ctxt->ctxtType = typeDecl;
11240 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011241 }
11242 /* Base type:
11243 * 2 If the <list> or <union> alternative is chosen,
11244 * then the ·simple ur-type definition·.
11245 */
11246 if (typeDecl->subtypes->type ==
11247 XML_SCHEMA_TYPE_LIST) {
11248 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11249 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11250 } else if (typeDecl->subtypes->type ==
11251 XML_SCHEMA_TYPE_UNION) {
11252 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11253 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11254 } else if (typeDecl->subtypes->type ==
11255 XML_SCHEMA_TYPE_RESTRICTION) {
11256 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
11257
11258 /*
11259 * Variety
11260 * If the <restriction> alternative is chosen, then the
11261 * {variety} of the {base type definition}.
11262 */
11263 if (typeDecl->baseType != NULL) {
11264 if (typeDecl->baseType->flags &
11265 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
11266 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
11267 else if (typeDecl->baseType->flags &
11268 XML_SCHEMAS_TYPE_VARIETY_LIST)
11269 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11270 else if (typeDecl->baseType->flags &
11271 XML_SCHEMAS_TYPE_VARIETY_UNION)
11272 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11273 /*
11274 * Schema Component Constraint: Simple Type Restriction
11275 * (Facets)
11276 * NOTE: Satisfaction of 1 and 2 arise from the fixup
11277 * applied beforehand.
11278 *
11279 * 3 The {facets} of R are the union of S and the {facets}
11280 * of B, eliminating duplicates. To eliminate duplicates,
11281 * when a facet of the same kind occurs in both S and the
11282 * {facets} of B, the one in the {facets} of B is not
11283 * included, with the exception of enumeration and pattern
11284 * facets, for which multiple occurrences with distinct values
11285 * are allowed.
11286 */
11287 if (typeDecl->baseType->facetSet != NULL) {
11288 last = typeDecl->facetSet;
11289 if (last != NULL)
11290 while (last->next != NULL)
11291 last = last->next;
11292 cur = typeDecl->baseType->facetSet;
11293 for (; cur != NULL; cur = cur->next) {
11294 /*
11295 * Base patterns won't be add here:
11296 * they are ORed in a type and
11297 * ANDed in derived types. This will
11298 * happed at validation level by
11299 * walking the base axis of the type.
11300 */
11301 if (cur->facet->type ==
11302 XML_SCHEMA_FACET_PATTERN)
11303 continue;
11304 facet = NULL;
11305 if ((typeDecl->facetSet != NULL) &&
11306 (cur->facet->type !=
11307 XML_SCHEMA_FACET_PATTERN) &&
11308 (cur->facet->type !=
11309 XML_SCHEMA_FACET_ENUMERATION)) {
11310 facet = typeDecl->facetSet;
11311 do {
11312 if (cur->facet->type ==
11313 facet->facet->type)
11314 break;
11315 facet = facet->next;
11316 } while (facet != NULL);
11317 }
11318 if (facet == NULL) {
11319 facet = (xmlSchemaFacetLinkPtr)
11320 xmlMalloc(sizeof(xmlSchemaFacetLink));
11321 if (facet == NULL) {
11322 xmlSchemaPErrMemory(ctxt,
11323 "fixing simpleType", NULL);
11324 return;
11325 }
11326 facet->facet = cur->facet;
11327 facet->next = NULL;
11328 if (last == NULL)
11329 typeDecl->facetSet = facet;
11330 else
11331 last->next = facet;
11332 last = facet;
11333 }
11334 }
11335 }
11336 }
11337 }
11338 /*
11339 * Check constraints.
11340 */
11341 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011342 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011343 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011344 case XML_SCHEMA_TYPE_SEQUENCE:
11345 case XML_SCHEMA_TYPE_GROUP:
11346 case XML_SCHEMA_TYPE_ALL:
11347 case XML_SCHEMA_TYPE_CHOICE:
11348 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11349 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011350 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +000011351 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011352 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11353 break;
11354 case XML_SCHEMA_TYPE_UNION:
11355 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
11356 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11357 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011358 case XML_SCHEMA_TYPE_BASIC:
11359 case XML_SCHEMA_TYPE_ANY:
11360 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011361 case XML_SCHEMA_TYPE_UR:
11362 case XML_SCHEMA_TYPE_ELEMENT:
11363 case XML_SCHEMA_TYPE_ATTRIBUTE:
11364 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000011365 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011366 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011367 case XML_SCHEMA_FACET_MININCLUSIVE:
11368 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11369 case XML_SCHEMA_FACET_MAXINCLUSIVE:
11370 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11371 case XML_SCHEMA_FACET_TOTALDIGITS:
11372 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11373 case XML_SCHEMA_FACET_PATTERN:
11374 case XML_SCHEMA_FACET_ENUMERATION:
11375 case XML_SCHEMA_FACET_WHITESPACE:
11376 case XML_SCHEMA_FACET_LENGTH:
11377 case XML_SCHEMA_FACET_MAXLENGTH:
11378 case XML_SCHEMA_FACET_MINLENGTH:
11379 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011380 if (typeDecl->subtypes != NULL)
11381 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011382 break;
11383 }
11384 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011385#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011386 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011387 xmlGenericError(xmlGenericErrorContext,
11388 "Type of %s : %s:%d :", name,
11389 typeDecl->node->doc->URL,
11390 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011391 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011393 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011394 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011395 case XML_SCHEMA_CONTENT_SIMPLE:
11396 xmlGenericError(xmlGenericErrorContext, "simple\n");
11397 break;
11398 case XML_SCHEMA_CONTENT_ELEMENTS:
11399 xmlGenericError(xmlGenericErrorContext, "elements\n");
11400 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011401 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011402 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
11403 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011404 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011405 xmlGenericError(xmlGenericErrorContext, "empty\n");
11406 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011407 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011408 xmlGenericError(xmlGenericErrorContext, "mixed\n");
11409 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011410 /* Removed, since not used. */
11411 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000011412 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011413 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
11414 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011415 */
Daniel Veillard8651f532002-04-17 09:06:27 +000011416 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011417 xmlGenericError(xmlGenericErrorContext, "basic\n");
11418 break;
11419 default:
11420 xmlGenericError(xmlGenericErrorContext,
11421 "not registered !!!\n");
11422 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011423 }
11424#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011425}
11426
11427/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011428 * xmlSchemaCheckFacet:
11429 * @facet: the facet
11430 * @typeDecl: the schema type definition
11431 * @ctxt: the schema parser context or NULL
11432 * @name: name of the type
11433 *
11434 * Checks the default values types, especially for facets
11435 *
11436 * Returns 0 if okay or -1 in cae of error
11437 */
11438int
11439xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011440 xmlSchemaTypePtr typeDecl,
11441 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011442{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000011443 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011444 int ret = 0;
11445
11446 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011447 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011448 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011449 }
11450 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011451 case XML_SCHEMA_FACET_MININCLUSIVE:
11452 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11453 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011454 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11455 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011456 /*
11457 * Okay we need to validate the value
11458 * at that point.
11459 */
11460 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011461 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011462
11463 /* 4.3.5.5 Constraints on enumeration Schema Components
11464 * Schema Component Constraint: enumeration valid restriction
11465 * It is an ·error· if any member of {value} is not in the
11466 * ·value space· of {base type definition}.
11467 *
11468 * minInclusive, maxInclusive, minExclusive, maxExclusive:
11469 * The value ·must· be in the
11470 * ·value space· of the ·base type·.
11471 */
11472 /*
11473 * This function is intended to deliver a compiled value
11474 * on the facet. In XML Schemas the type holding a facet,
11475 * cannot be a built-in type. Thus to ensure that other API
11476 * calls (relaxng) do work, if the given type is a built-in
11477 * type, we will assume that the given built-in type *is
11478 * already* the base type.
11479 */
11480 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
11481 base = typeDecl->baseType;
11482 if (base == NULL) {
11483 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011484 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011485 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011486 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011487 typeDecl->name, NULL);
11488 return (-1);
11489 }
11490 } else
11491 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011492 /*
11493 * TODO: Try to avoid creating a new context.
11494 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011495 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011496 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011497 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011498 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011499 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011500 "creating a new validation context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011501 NULL, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011502 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011503 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011504 vctxt->type = base;
11505 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011506 facet->val = vctxt->value;
11507 vctxt->value = NULL;
11508 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011509 /* error code */
11510 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011511 xmlSchemaPErrExt(ctxt, facet->node,
11512 XML_SCHEMAP_INVALID_FACET,
11513 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011514 "Type definition '%s': The value '%s' of the "
11515 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011516 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011517 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011518 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 }
11520 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011521 } else if (ret < 0) {
11522 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011523 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011524 NULL, NULL, NULL,
11525 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011526 "failed to validate the value '%s' name of the "
11527 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011528 facet->value,
11529 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
11530 base->name, NULL, NULL);
11531 ret = -1;
11532 }
11533 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011534 break;
11535 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011536 case XML_SCHEMA_FACET_PATTERN:
11537 facet->regexp = xmlRegexpCompile(facet->value);
11538 if (facet->regexp == NULL) {
11539 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011540 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011541 "Type definition '%s': The value '%s' of the "
11542 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011543 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011544 ret = -1;
11545 }
11546 break;
11547 case XML_SCHEMA_FACET_TOTALDIGITS:
11548 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11549 case XML_SCHEMA_FACET_LENGTH:
11550 case XML_SCHEMA_FACET_MAXLENGTH:
11551 case XML_SCHEMA_FACET_MINLENGTH:{
11552 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011553
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011554 tmp =
11555 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
11556 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000011557 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011558 if (tmp != 0) {
11559 /* error code */
11560 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011561 xmlSchemaPErrExt(ctxt, facet->node,
11562 XML_SCHEMAP_INVALID_FACET_VALUE,
11563 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011564 "Type definition '%s': The value '%s' of the "
11565 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011566 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011567 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011568 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011569 }
11570 ret = -1;
11571 }
11572 break;
11573 }
11574 case XML_SCHEMA_FACET_WHITESPACE:{
11575 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
11576 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
11577 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
11578 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
11579 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
11580 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
11581 } else {
11582 if (ctxt != NULL) {
11583 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011584 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011585 "Type definition '%s': The value '%s' of the "
11586 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011587 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011588 }
11589 ret = -1;
11590 }
11591 }
11592 default:
11593 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011594 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011595 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011596}
11597
11598/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011599 * xmlSchemaCheckDefaults:
11600 * @typeDecl: the schema type definition
11601 * @ctxt: the schema parser context
11602 *
11603 * Checks the default values types, especially for facets
11604 */
11605static void
11606xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011607 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011608{
Daniel Veillard4255d502002-04-16 15:50:10 +000011609 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011610 name = typeDecl->name;
11611 /*
11612 * NOTE: It is intended to use the facets list, instead
11613 * of facetSet.
11614 */
11615 if (typeDecl->facets != NULL) {
11616 xmlSchemaFacetPtr facet = typeDecl->facets;
11617
11618 while (facet != NULL) {
11619 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
11620 facet = facet->next;
11621 }
11622 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011623}
11624
11625/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000011626 * xmlSchemaAttrGrpFixup:
11627 * @attrgrpDecl: the schema attribute definition
11628 * @ctxt: the schema parser context
11629 * @name: the attribute name
11630 *
11631 * Fixes finish doing the computations on the attributes definitions
11632 */
11633static void
Daniel Veillard3646d642004-06-02 19:19:14 +000011634xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011635 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000011636{
11637 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011638 name = attrgrp->name;
11639 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011640 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000011641 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011642 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000011643
Daniel Veillardc0826a72004-08-10 14:17:33 +000011644 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
11645 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011646 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011647 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011649 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
11650 "ref", attrgrp->ref, attrgrp->refNs,
11651 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011652 return;
11653 }
11654 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011655 attrgrp->attributes = ref->attributes;
11656 attrgrp->attributeWildcard = ref->attributeWildcard;
11657 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000011658}
11659
11660/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011661 * xmlSchemaAttrFixup:
11662 * @attrDecl: the schema attribute definition
11663 * @ctxt: the schema parser context
11664 * @name: the attribute name
11665 *
11666 * Fixes finish doing the computations on the attributes definitions
11667 */
11668static void
11669xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011670 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011671{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011672 /*
11673 * TODO: If including this is done twice (!) for every attribute.
11674 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011675 /*
11676 * The simple type definition corresponding to the <simpleType> element
11677 * information item in the [children], if present, otherwise the simple
11678 * type definition ·resolved· to by the ·actual value· of the type
11679 * [attribute], if present, otherwise the ·simple ur-type definition·.
11680 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011681 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
11682 return;
11683 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000011684 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011685 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000011686 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011687 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011688 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011689 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011690
Daniel Veillard01fa6152004-06-29 17:04:39 +000011691 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
11692 attrDecl->typeNs);
11693 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011694 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011695 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011696 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11697 "type", attrDecl->typeName, attrDecl->typeNs,
11698 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011700 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011701 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011702 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000011703
Daniel Veillardc0826a72004-08-10 14:17:33 +000011704 /*
11705 * TODO: Evaluate, what errors could occur if the declaration is not
11706 * found. It might be possible that the "typefixup" might crash if
11707 * no ref declaration was found.
11708 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011709 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011710 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011711 xmlSchemaPResCompAttrErr(ctxt,
11712 XML_SCHEMAP_SRC_RESOLVE,
11713 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11714 "ref", attrDecl->ref, attrDecl->refNs,
11715 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011716 return;
11717 }
11718 xmlSchemaAttrFixup(ref, ctxt, NULL);
11719 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011720 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011721 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000011722 }
11723}
11724
11725/**
11726 * xmlSchemaParse:
11727 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011728 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011729 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000011730 * XML Shema struture which can be used to validate instances.
11731 * *WARNING* this interface is highly subject to change
11732 *
11733 * Returns the internal XML Schema structure built from the resource or
11734 * NULL in case of error
11735 */
11736xmlSchemaPtr
11737xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
11738{
11739 xmlSchemaPtr ret = NULL;
11740 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011741 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011742 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011743 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011744
11745 xmlSchemaInitTypes();
11746
Daniel Veillard6045c902002-10-09 21:13:59 +000011747 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000011748 return (NULL);
11749
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011750 nberrors = ctxt->nberrors;
11751 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011752 ctxt->counter = 0;
11753 ctxt->container = NULL;
11754
11755 /*
11756 * First step is to parse the input document into an DOM/Infoset
11757 */
Daniel Veillard6045c902002-10-09 21:13:59 +000011758 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011759 doc = xmlReadFile((const char *) ctxt->URL, NULL,
11760 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011761 if (doc == NULL) {
11762 xmlSchemaPErr(ctxt, NULL,
11763 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011764 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011765 ctxt->URL, NULL);
11766 return (NULL);
11767 }
Daniel Veillard6045c902002-10-09 21:13:59 +000011768 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011769 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
11770 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011771 if (doc == NULL) {
11772 xmlSchemaPErr(ctxt, NULL,
11773 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011774 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011775 NULL, NULL);
11776 return (NULL);
11777 }
11778 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000011779 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000011780 } else if (ctxt->doc != NULL) {
11781 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011782 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000011783 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011784 xmlSchemaPErr(ctxt, NULL,
11785 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011786 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011787 NULL, NULL);
11788 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011789 }
11790
11791 /*
11792 * Then extract the root and Schema parse it
11793 */
11794 root = xmlDocGetRootElement(doc);
11795 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011796 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11797 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011798 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000011799 if (!preserve) {
11800 xmlFreeDoc(doc);
11801 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011802 return (NULL);
11803 }
11804
11805 /*
11806 * Remove all the blank text nodes
11807 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011808 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000011809
11810 /*
11811 * Then do the parsing for good
11812 */
11813 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000011814 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000011815 if (!preserve) {
11816 xmlFreeDoc(doc);
11817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011818 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000011819 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011820 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011821 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000011822 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011823 ctxt->ctxtType = NULL;
11824 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011825 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011826 * Then fixup all attributes declarations
11827 */
11828 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
11829
11830 /*
11831 * Then fixup all attributes group declarations
11832 */
11833 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
11834 ctxt);
11835
11836 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000011837 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000011838 */
11839 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
11840
11841 /*
11842 * Then fix references of element declaration; apply constraints.
11843 */
11844 xmlHashScanFull(ret->elemDecl,
11845 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011846
11847 /*
11848 * Then build the content model for all elements
11849 */
11850 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011851 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011852
11853 /*
11854 * Then check the defaults part of the type like facets values
11855 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011856 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
11857 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011858
Daniel Veillardc0826a72004-08-10 14:17:33 +000011859
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011860 if (ctxt->nberrors != 0) {
11861 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011862 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011863 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011864 return (ret);
11865}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011866
Daniel Veillard4255d502002-04-16 15:50:10 +000011867/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000011868 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000011869 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000011870 * @err: the error callback
11871 * @warn: the warning callback
11872 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000011873 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011874 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011875 */
11876void
11877xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011878 xmlSchemaValidityErrorFunc err,
11879 xmlSchemaValidityWarningFunc warn, void *ctx)
11880{
Daniel Veillard4255d502002-04-16 15:50:10 +000011881 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011882 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011883 ctxt->error = err;
11884 ctxt->warning = warn;
11885 ctxt->userData = ctx;
11886}
11887
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011888/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000011889 * xmlSchemaGetParserErrors:
11890 * @ctxt: a XMl-Schema parser context
11891 * @err: the error callback result
11892 * @warn: the warning callback result
11893 * @ctx: contextual data for the callbacks result
11894 *
11895 * Get the callback information used to handle errors for a parser context
11896 *
11897 * Returns -1 in case of failure, 0 otherwise
11898 */
11899int
11900xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
11901 xmlSchemaValidityErrorFunc * err,
11902 xmlSchemaValidityWarningFunc * warn, void **ctx)
11903{
11904 if (ctxt == NULL)
11905 return(-1);
11906 if (err != NULL)
11907 *err = ctxt->error;
11908 if (warn != NULL)
11909 *warn = ctxt->warning;
11910 if (ctx != NULL)
11911 *ctx = ctxt->userData;
11912 return(0);
11913}
11914
11915/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011916 * xmlSchemaFacetTypeToString:
11917 * @type: the facet type
11918 *
11919 * Convert the xmlSchemaTypeType to a char string.
11920 *
11921 * Returns the char string representation of the facet type if the
11922 * type is a facet and an "Internal Error" string otherwise.
11923 */
11924static const char *
11925xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
11926{
11927 switch (type) {
11928 case XML_SCHEMA_FACET_PATTERN:
11929 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011930 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011931 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011932 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011933 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011934 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011935 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011936 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011937 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011938 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011939 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011940 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011941 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011942 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011943 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011944 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011945 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011946 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011947 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011948 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011949 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011950 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011951 return ("fractionDigits");
11952 default:
11953 break;
11954 }
11955 return ("Internal Error");
11956}
11957
Daniel Veillardc0826a72004-08-10 14:17:33 +000011958static xmlChar *
11959xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
11960 const xmlChar *cur = value;
11961 xmlChar *ret = NULL, *mcur;
11962
11963 if (value == NULL)
11964 return(NULL);
11965
11966 while ((*cur != 0) &&
11967 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
11968 cur++;
11969 }
11970 if (*cur == 0)
11971 return (NULL);
11972 ret = xmlStrdup(value);
11973 /* TODO FIXME: I guess gcc will bark at this. */
11974 mcur = (xmlChar *) (ret + (cur - value));
11975 do {
11976 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
11977 *mcur = ' ';
11978 mcur++;
11979 } while (*mcur != 0);
11980 return(ret);
11981}
11982
11983static int
11984xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
11985{
11986 xmlSchemaTypePtr anc;
11987
11988 /*
11989 * The normalization type can be changed only for types which are derived
11990 * from xsd:string.
11991 */
11992 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11993 if ((type->builtInType == XML_SCHEMAS_STRING) &&
11994 (type->builtInType == XML_SCHEMAS_NORMSTRING))
11995
11996 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11997 else {
11998 /*
11999 * For all ·atomic· datatypes other than string (and types ·derived·
12000 * by ·restriction· from it) the value of whiteSpace is fixed to
12001 * collapse
12002 */
12003 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12004 }
12005 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12006 /*
12007 * For list types the facet "whiteSpace" is fixed to "collapse".
12008 */
12009 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12010 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12011 return (-1);
12012 } else if (type->facetSet != NULL) {
12013 xmlSchemaTypePtr anyST;
12014 xmlSchemaFacetLinkPtr lin;
12015
12016 /*
12017 * Atomic types.
12018 */
12019 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12020 anc = type->baseType;
12021 do {
12022 /*
12023 * For all ·atomic· datatypes other than string (and types ·derived·
12024 * by ·restriction· from it) the value of whiteSpace is fixed to
12025 * collapse
12026 */
12027 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
12028 (anc->builtInType == XML_SCHEMAS_STRING)) {
12029
12030 lin = type->facetSet;
12031 do {
12032 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
12033 if (lin->facet->whitespace ==
12034 XML_SCHEMAS_FACET_COLLAPSE) {
12035 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12036 } else if (lin->facet->whitespace ==
12037 XML_SCHEMAS_FACET_REPLACE) {
12038 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
12039 } else
12040 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12041 break;
12042 }
12043 lin = lin->next;
12044 } while (lin != NULL);
12045 break;
12046 }
12047 anc = anc->baseType;
12048 } while (anc != anyST);
12049 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12050 }
12051 return (-1);
12052}
12053
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012054/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000012055 * xmlSchemaValidateFacetsInternal:
12056 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000012057 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000012058 * @facets: the list of facets to check
12059 * @value: the lexical repr of the value to validate
12060 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000012061 * @fireErrors: if 0, only internal errors will be fired;
12062 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000012063 *
12064 * Check a value against all facet conditions
12065 *
12066 * Returns 0 if the element is schemas valid, a positive error code
12067 * number otherwise and -1 in case of internal or API error.
12068 */
12069static int
12070xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012071 xmlSchemaTypePtr type,
12072 const xmlChar * value,
12073 unsigned long length,
12074 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012075{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012076 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012077 xmlSchemaTypePtr biType; /* The build-in type. */
12078 xmlSchemaTypePtr tmpType;
12079 xmlSchemaFacetLinkPtr facetLink;
12080 int retFacet, hasFacet;
12081 xmlSchemaFacetPtr facet;
12082 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012083
Daniel Veillardc0826a72004-08-10 14:17:33 +000012084#ifdef DEBUG_UNION_VALIDATION
12085 printf("Facets of type: '%s'\n", (const char *) type->name);
12086 printf(" fireErrors: %d\n", fireErrors);
12087#endif
12088
12089 /*
12090 * NOTE: Do not jump away, if the facetSet of the given type is
12091 * empty: until now, "pattern" facets of the *base types* need to
12092 * be checked as well.
12093 */
12094 biType = type->baseType;
12095 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12096 biType = biType->baseType;
12097 if (biType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012098 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012099 "Internal error: xmlSchemaValidateFacetsInternal, "
12100 "the base type axis of the given type '%s' does not resolve to "
12101 "a built-in type.\n",
12102 type->name, NULL);
12103 return (-1);
12104 }
12105
12106 if (type->facetSet != NULL) {
12107 facetLink = type->facetSet;
12108 while (facetLink != NULL) {
12109 facet = facetLink->facet;
12110 /*
12111 * Skip the pattern "whiteSpace": it is used to
12112 * format the character content beforehand.
12113 */
12114 switch (facet->type) {
12115 case XML_SCHEMA_FACET_WHITESPACE:
12116 case XML_SCHEMA_FACET_PATTERN:
12117 case XML_SCHEMA_FACET_ENUMERATION:
12118 break;
12119 case XML_SCHEMA_FACET_LENGTH:
12120 case XML_SCHEMA_FACET_MINLENGTH:
12121 case XML_SCHEMA_FACET_MAXLENGTH:
12122 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12123 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12124 value, length, 0);
12125 len = length;
12126 } else
12127 ret = xmlSchemaValidateLengthFacet(biType, facet,
12128 value, ctxt->value, &len);
12129 break;
12130 default:
12131 ret = xmlSchemaValidateFacet(biType, facet, value,
12132 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012134 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012135 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012136 "Internal error: xmlSchemaValidateFacetsInternal, "
12137 "validating facet of type '%s'.\n",
12138 type->name, NULL);
12139 break;
12140 } else if ((ret > 0) && (fireErrors)) {
12141 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, len,
12142 type, facet, NULL, NULL, NULL, NULL);
12143 }
12144
12145 facetLink = facetLink->next;
12146 }
12147 if (ret >= 0) {
12148 /*
12149 * Process enumerations.
12150 */
12151 retFacet = 0;
12152 facetLink = type->facetSet;
12153 while (facetLink != NULL) {
12154 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12155 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12156 value, ctxt->value);
12157 if (retFacet <= 0)
12158 break;
12159 }
12160 facetLink = facetLink->next;
12161 }
12162 if (retFacet > 0) {
12163 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12164 if (fireErrors)
12165 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur,
12166 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12167 } else if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012168 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012169 "Internal error: xmlSchemaValidateFacetsInternal, "
12170 "validating facet of type '%s'.\n",
12171 BAD_CAST "enumeration", NULL);
12172 ret = -1;
12173 }
12174 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012175 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012176 if (ret >= 0) {
12177 /*
12178 * Process patters. Pattern facets are ORed at type level
12179 * and ANDed if derived. Walk the base type axis.
12180 */
12181 hasFacet = 0;
12182 tmpType = type;
12183 facet = NULL;
12184 do {
12185 retFacet = 0;
12186 for (facetLink = tmpType->facetSet; facetLink != NULL;
12187 facetLink = facetLink->next) {
12188 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
12189 continue;
12190 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12191 value, ctxt->value);
12192 if (retFacet <= 0)
12193 break;
12194 else
12195 /* Save the last non-validating facet. */
12196 facet = facetLink->facet;
12197 }
12198 if (retFacet != 0)
12199 break;
12200 tmpType = tmpType->baseType;
12201 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
12202 if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012203 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012204 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12205 "validating 'pattern' facets of type '%s'.\n",
12206 tmpType->name, NULL);
12207 ret = -1;
12208 } else if (retFacet > 0) {
12209 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
12210 if (fireErrors) {
12211 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, 0, type, facet,
12212 NULL, NULL, NULL, NULL);
12213 }
12214 }
12215 }
12216
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012217 return (ret);
12218}
12219
Daniel Veillard4255d502002-04-16 15:50:10 +000012220/************************************************************************
12221 * *
12222 * Simple type validation *
12223 * *
12224 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000012225
Daniel Veillard4255d502002-04-16 15:50:10 +000012226
12227/************************************************************************
12228 * *
12229 * DOM Validation code *
12230 * *
12231 ************************************************************************/
12232
12233static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012234 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012235static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012236 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000012237 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012238static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012239 xmlNodePtr elem,
12240 xmlSchemaElementPtr elemDecl,
12241 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012242
Daniel Veillard3646d642004-06-02 19:19:14 +000012243
12244/**
12245 * xmlSchemaFreeAttrStates:
12246 * @state: a list of attribute states
12247 *
12248 * Free the given list of attribute states
12249 *
12250 */
12251static void
12252xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
12253{
12254 xmlSchemaAttrStatePtr tmp;
12255 while (state != NULL) {
12256 tmp = state;
12257 state = state->next;
12258 xmlFree(tmp);
12259 }
12260}
12261
Daniel Veillard4255d502002-04-16 15:50:10 +000012262/**
12263 * xmlSchemaRegisterAttributes:
12264 * @ctxt: a schema validation context
12265 * @attrs: a list of attributes
12266 *
12267 * Register the list of attributes as the set to be validated on that element
12268 *
12269 * Returns -1 in case of error, 0 otherwise
12270 */
12271static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012272xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
12273{
Daniel Veillard3646d642004-06-02 19:19:14 +000012274 xmlSchemaAttrStatePtr tmp;
12275
12276 ctxt->attr = NULL;
12277 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012278 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012279 if ((attrs->ns != NULL) &&
12280 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
12281 attrs = attrs->next;
12282 continue;
12283 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012284 tmp = (xmlSchemaAttrStatePtr)
12285 xmlMalloc(sizeof(xmlSchemaAttrState));
12286 if (tmp == NULL) {
12287 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
12288 return (-1);
12289 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012290 tmp->attr = attrs;
12291 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
12292 tmp->next = NULL;
12293 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012294 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012295 else
12296 ctxt->attrTop->next = tmp;
12297 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012298 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012299 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012300 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012301}
12302
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012303#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000012304/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012305 * xmlSchemaValidateCheckNodeList
12306 * @nodelist: the list of nodes
12307 *
12308 * Check the node list is only made of text nodes and entities pointing
12309 * to text nodes
12310 *
12311 * Returns 1 if true, 0 if false and -1 in case of error
12312 */
12313static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012314xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
12315{
Daniel Veillard4255d502002-04-16 15:50:10 +000012316 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012317 if (nodelist->type == XML_ENTITY_REF_NODE) {
12318 TODO /* implement recursion in the entity content */
12319 }
12320 if ((nodelist->type != XML_TEXT_NODE) &&
12321 (nodelist->type != XML_COMMENT_NODE) &&
12322 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000012323 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012324 return (0);
12325 }
12326 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012327 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012328 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012329}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012330#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012331
12332/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012333 * xmlSchemaValidateCallback:
12334 * @ctxt: a schema validation context
12335 * @name: the name of the element detected (might be NULL)
12336 * @type: the type
12337 *
12338 * A transition has been made in the automata associated to an element
12339 * content model
12340 */
12341static void
12342xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012343 const xmlChar * name ATTRIBUTE_UNUSED,
12344 xmlSchemaTypePtr type, xmlNodePtr node)
12345{
Daniel Veillard4255d502002-04-16 15:50:10 +000012346 xmlSchemaTypePtr oldtype = ctxt->type;
12347 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012348
Daniel Veillard4255d502002-04-16 15:50:10 +000012349#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000012350 xmlGenericError(xmlGenericErrorContext,
12351 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012352 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012353#endif
12354 ctxt->type = type;
12355 ctxt->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012356 xmlSchemaValidateContent(ctxt, node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012357 ctxt->type = oldtype;
12358 ctxt->node = oldnode;
12359}
12360
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361/**
12362 * xmlSchemaValidateSimpleTypeValue:
12363 * @ctxt: a schema validation context
12364 * @value: the value to be validated
12365 * @fireErrors: shall errors be reported?
12366 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000012367 * @normalize: shall the value be normalized?
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 *
12369 * Validates a value by the given type (user derived or built-in).
12370 *
12371 * Returns 0 if the value is valid, a positive error code
12372 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012373 */
12374static int
12375xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
12376 const xmlChar *value,
12377 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012378 int applyFacets,
12379 int normalize)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380{
12381 xmlSchemaTypePtr type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012382 int ret = 0;
12383 xmlChar *normValue = NULL;
12384 int wtsp;
12385
12386 type = ctxt->type;
12387 wtsp = ctxt->valueWS;
12388 /*
12389 * Normalize the value.
12390 */
12391 if (normalize &&
12392 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
12393 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
12394
12395 if ((norm != -1) && (norm > ctxt->valueWS)) {
12396 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12397 normValue = xmlSchemaCollapseString(value);
12398 else
12399 normValue = xmlSchemaWhiteSpaceReplace(value);
12400 ctxt->valueWS = norm;
12401 if (normValue != NULL)
12402 value = (const xmlChar *) normValue;
12403 }
12404 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012405 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
12406 xmlSchemaTypePtr base, anyType;
12407
12408 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12409
12410 base = type->baseType;
12411 while ((base != NULL) &&
12412 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
12413 (base->type != XML_SCHEMA_TYPE_BASIC) &&
12414 (base != anyType)) {
12415 base = base->baseType;
12416 }
12417 ctxt->type = base;
12418 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 0, 1);
12419 ctxt->type = type;
12420 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012421 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012422 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12423 "validating complex type '%s'\n",
12424 type->name, NULL);
12425 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12426 /*
12427 * Check facets.
12428 */
12429 /*
12430 * This is somehow not nice, since if an error occurs
12431 * the reported type will be the complex type; the spec
12432 * wants a simple type to be created on the complex type
12433 * if it has a simple content. For now we have to live with
12434 * it.
12435 */
12436 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12437 value, 0, fireErrors);
12438 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012439 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012440 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12441 "validating facets of complex type '%s'\n",
12442 type->name, NULL);
12443 } else if (ret > 0) {
12444 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
12445 /*
12446 Disabled, since the facet validation already reports errors.
12447 if (fireErrors)
12448 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12449 */
12450 }
12451 }
12452 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012453 xmlNodePtr child;
12454
12455 if (ctxt->value != NULL) {
12456 xmlSchemaFreeValue(ctxt->value);
12457 ctxt->value = NULL;
12458 }
12459 child = ctxt->node;
12460 while (child != NULL) {
12461 switch (child->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012462 case XML_TEXT_NODE:
12463 case XML_CDATA_SECTION_NODE:
12464 case XML_PI_NODE:
12465 case XML_COMMENT_NODE:
12466 case XML_XINCLUDE_START:
12467 case XML_XINCLUDE_END:
12468 break;
12469 case XML_ENTITY_REF_NODE:
12470 case XML_ENTITY_NODE:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012471 /* TODO: Scour the entities for illegal nodes. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012472 TODO break;
12473 case XML_ELEMENT_NODE: {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012474 /* NOTE: Changed to an internal error, since the
12475 * existence of an element node will be already checked in
12476 * xmlSchemaValidateSimpleTypeElement and in
12477 * xmlSchemaValidateComplexType.
12478 */
12479 xmlSchemaVCustomErr(ctxt,
12480 XML_SCHEMAV_INTERNAL,
12481 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12482 ctxt->cur, type,
12483 "Element found in content", NULL);
12484 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012485 }
12486 case XML_ATTRIBUTE_NODE:
12487 case XML_DOCUMENT_NODE:
12488 case XML_DOCUMENT_TYPE_NODE:
12489 case XML_DOCUMENT_FRAG_NODE:
12490 case XML_NOTATION_NODE:
12491 case XML_HTML_DOCUMENT_NODE:
12492 case XML_DTD_NODE:
12493 case XML_ELEMENT_DECL:
12494 case XML_ATTRIBUTE_DECL:
12495 case XML_ENTITY_DECL:
12496 case XML_NAMESPACE_DECL:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012497#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardc0826a72004-08-10 14:17:33 +000012498 case XML_DOCB_DOCUMENT_NODE:
12499#endif
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012500 {
12501 xmlSchemaVCustomErr(ctxt,
12502 XML_SCHEMAV_INTERNAL,
12503 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12504 ctxt->cur, NULL,
12505 "Node of unexpected type found in content",
12506 NULL);
12507 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012508 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012509 }
12510 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012511
12512 }
12513 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), ctxt->cur);
12514 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012515 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
12516 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
12517 else
12518 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012519 if (fireErrors)
12520 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012521 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012522 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012523 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012524 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012525 }
12526 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12527 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
12528 * a literal in the ·lexical space· of {base type definition}
12529 */
12530 ctxt->type = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012531 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0, 0);
12532 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012533 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012534 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012535 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012536 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012537 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012538 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012539 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012540 if (fireErrors)
12541 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12542 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012543 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012544 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012545 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012546 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12547 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012548 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012549 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012550 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012551 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012552 type->name, NULL);
12553 } else if (ret > 0) {
12554 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 /*
12556 Disabled, since the facet validation already reports errors.
12557 if (fireErrors)
12558 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12559 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 }
12561 }
12562 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12563
12564 xmlSchemaTypePtr tmpType;
12565 const xmlChar *cur, *end;
12566 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012567 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012568
12569 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
12570 * of white space separated tokens, each of which ·match·es a literal
12571 * in the ·lexical space· of {item type definition}
12572 */
12573
Daniel Veillardc0826a72004-08-10 14:17:33 +000012574 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012575 cur = value;
12576 do {
12577 while (IS_BLANK_CH(*cur))
12578 cur++;
12579 end = cur;
12580 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
12581 end++;
12582 if (end == cur)
12583 break;
12584 tmp = xmlStrndup(cur, end - cur);
12585 len++;
12586 ctxt->type = tmpType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012587 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1, 0);
12588 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012589 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012590 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012591 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012592 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12593 "validating an item of list simple type '%s'\n",
12594 type->name, NULL);
12595 break;
12596 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012597 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012598 if (fireErrors)
12599 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012600 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012601 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012602 cur = end;
12603 } while (*cur != 0);
12604 /*
12605 * Check facets.
12606 */
12607 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012608 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012609 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012610 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012611 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012612 } else if ((ret == 0) && (applyFacets)) {
12613 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12614 value, len, fireErrors);
12615 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012616 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012617 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12618 "validating facets of list simple type '%s'\n",
12619 type->name, NULL);
12620 } else if (ret > 0) {
12621 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012622 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012623 Disabled, since the facet validation already reports errors.
12624 if (fireErrors)
12625 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012626 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012627 }
12628
Daniel Veillard01fa6152004-06-29 17:04:39 +000012629 }
12630 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12631 xmlSchemaTypeLinkPtr memberLink;
12632
12633 /*
12634 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
12635 * not apply directly; however, the normalization behavior of ·union·
12636 * types is controlled by the value of whiteSpace on that one of the
12637 * ·memberTypes· against which the ·union· is successfully validated.
12638 *
12639 * This means that the value is normalized by the first validating
12640 * member type, then the facets of the union type are applied. This
12641 * needs changing of the value!
12642 */
12643
12644 /*
12645 * 1.2.3 if {variety} is ·union· then the string must ·match· a
12646 * literal in the ·lexical space· of at least one member of
12647 * {member type definitions}
12648 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649#ifdef DEBUG_UNION_VALIDATION
12650 printf("Union ST : '%s'\n", (const char *) type->name);
12651 printf(" fireErrors : %d\n", fireErrors);
12652 printf(" applyFacets: %d\n", applyFacets);
12653#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000012654 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
12655 if (memberLink == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012656 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012657 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012658 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012659 type->name, NULL);
12660 ret = -1;
12661 }
12662 if (ret == 0) {
12663 while (memberLink != NULL) {
12664 ctxt->type = memberLink->type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012665 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012666 if ((ret <= 0) || (ret == 0))
12667 break;
12668 memberLink = memberLink->next;
12669 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012670 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012671 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012672 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012673 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012674 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012675 type->name, NULL);
12676 } else if (ret > 0) {
12677 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012678 if (fireErrors)
12679 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12680 }
12681 }
12682 /*
12683 * Apply facets (pattern, enumeration).
12684 */
12685 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12686 int mws;
12687 /*
12688 * The normalization behavior of ·union· types is controlled by
12689 * the value of whiteSpace on that one of the ·memberTypes·
12690 * against which the ·union· is successfully validated.
12691 */
12692 if (normValue != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012693 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012694 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12695 "the value was already normalized for the union simple "
12696 "type '%s'.\n", type->name, NULL);
12697 }
12698 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
12699 if (mws > ctxt->valueWS) {
12700 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12701 normValue = xmlSchemaCollapseString(value);
12702 else
12703 normValue = xmlSchemaWhiteSpaceReplace(value);
12704 if (normValue != NULL)
12705 value = (const xmlChar *) normValue;
12706 }
12707
12708 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12709 value, 0, fireErrors);
12710 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012711 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012712 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12713 "validating facets of union simple type '%s'\n",
12714 type->name, NULL);
12715 } else if (ret > 0) {
12716 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
12717 /*
12718 if (fireErrors)
12719 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12720 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012721 }
12722 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012723 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012724 ctxt->type = type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012725 ctxt->valueWS = wtsp;
12726 if (normValue != NULL)
12727 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012728 return (ret);
12729}
12730
12731/**
12732 * xmlSchemaValidateSimpleTypeElement:
12733 * @ctxt: a schema validation context
12734 * @node: the element node to be validated.
12735 *
12736 * Validate the element against a simple type.
12737 *
12738 * Returns 0 if the element is valid, a positive error code
12739 * number otherwise and -1 in case of an internal or API error.
12740 */
12741static int
12742xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12743{
12744 xmlNodePtr child;
12745 xmlSchemaTypePtr type;
12746 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012747 int ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012748 xmlChar *value;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012749 xmlNodePtr cur;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012750
12751
12752 child = ctxt->node;
12753 type = ctxt->type;
12754
12755 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012756 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012757 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
12758 node->name, NULL);
12759 return (-1);
12760 }
12761
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012762 /*
12763 * cvc-type: 3.1.2 The element information item must have no element
12764 * information item [children].
12765 */
12766 cur = child;
12767 while (cur != NULL) {
12768 if (cur->type == XML_ELEMENT_NODE) {
12769 xmlSchemaVCustomErr(ctxt,
12770 XML_SCHEMAV_CVC_TYPE_3_1_2,
12771 node, type,
12772 "No element content allowed", NULL);
12773 return (XML_SCHEMAV_CVC_TYPE_3_1_2);
12774 }
12775 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012776 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012777
Daniel Veillard01fa6152004-06-29 17:04:39 +000012778 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012779 * cvc-type 3.1.1:
12780 *
12781 * The attributes of must be empty, excepting those whose namespace name
12782 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
12783 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
12784 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012785 attr = node->properties;
12786 while (attr != NULL) {
12787 if ((attr->ns == NULL) ||
12788 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
12789 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
12790 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
12791 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
12792 (!xmlStrEqual
12793 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012794 xmlSchemaVIllegalAttrErr(ctxt,
12795 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012796 return (ctxt->err);
12797 }
12798 attr = attr->next;
12799 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012800 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
12801 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
12802 value = xmlNodeGetContent(child);
12803 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
12804 if (value != NULL)
12805 xmlFree(value);
12806 ctxt->type = type;
12807 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012808 return (ret);
12809}
Daniel Veillard4255d502002-04-16 15:50:10 +000012810
12811/**
12812 * xmlSchemaValidateElementType:
12813 * @ctxt: a schema validation context
12814 * @node: the top node.
12815 *
12816 * Validate the content of an element type.
12817 * Validation Rule: Element Locally Valid (Complex Type)
12818 *
12819 * Returns 0 if the element is schemas valid, a positive error code
12820 * number otherwise and -1 in case of internal or API error.
12821 */
12822static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012823xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12824{
Daniel Veillard4255d502002-04-16 15:50:10 +000012825 xmlNodePtr child;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012826 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000012827 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000012828 int ret;
12829 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
12830
Daniel Veillard01fa6152004-06-29 17:04:39 +000012831 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000012832 /*
12833 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
12834 * go in here as well.
12835 */
12836
12837 /* TODO: Is this one called always with an element declaration as the
12838 * context's type?
12839 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012840
12841 oldregexp = ctxt->regexp;
12842
12843 child = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012844 decl = (xmlSchemaElementPtr) ctxt->type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012845
Daniel Veillardc0826a72004-08-10 14:17:33 +000012846 if ((ctxt == NULL) || (decl == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012847 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000012848 "Internal error: xmlSchemaValidateElementType\n",
12849 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012850 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012851 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012852 /*
12853 * TODO: Since this should be already checked by the content model automaton,
12854 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
12855 * has been changed to XML_SCHEMAV_INTERNAL.
12856 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012857 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012858 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012859 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
12860 /* XML_SCHEMAS_ERR_MISSING, */
12861 "Element %s: missing child %s\n",
12862 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012863 }
12864 return (ctxt->err);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012865 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012866
12867 /*
12868 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012869 * TODO, FIXME: Can this still happen here? Isn't this already checked
12870 * by the content model automaton?
12871 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012872 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012873 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
12874 /* XML_SCHEMAS_ERR_WRONGELEM, */
12875 "Element %s: missing child %s found %s\n",
12876 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012877 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012878 }
12879 /*
12880 * Verify the attributes
12881 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012882 /*
12883 * TODO: This "attrTop" thing is not needed any more.
12884 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012885 attrs = ctxt->attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012886 attrTop = ctxt->attrTop;
12887 xmlSchemaRegisterAttributes(ctxt, child->properties);
12888 xmlSchemaValidateAttributes(ctxt, child, decl->subtypes);
12889 if (ctxt->attr != NULL)
12890 xmlSchemaFreeAttributeStates(ctxt->attr);
12891 ctxt->attr = attrs;
12892 ctxt->attrTop = attrTop;
Daniel Veillard3646d642004-06-02 19:19:14 +000012893
Daniel Veillard4255d502002-04-16 15:50:10 +000012894 /*
12895 * Verify the element content recursively
Daniel Veillardc0826a72004-08-10 14:17:33 +000012896 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012897 oldregexp = ctxt->regexp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012898 /*
12899 * FIXME TODO: This one creates a regexp even if no content
12900 * model was defined. Somehow ->contModel is always not NULL
12901 * for complex types, even if they are empty.
12902 */
12903 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012904 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
12905 (xmlRegExecCallbacks)
12906 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012907#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012908 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012909#endif
12910 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012911 xmlSchemaValidateType(ctxt, child, decl, decl->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000012912
12913 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012914 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012915#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012916 xmlGenericError(xmlGenericErrorContext,
12917 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000012918#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012919 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012920 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
12921 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012922 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012923 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
12924 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012925#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012926 } else {
12927 xmlGenericError(xmlGenericErrorContext,
12928 "Element %s content check succeeded\n",
12929 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012930
12931#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012932 }
12933 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000012934 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012935 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000012936 ctxt->node = child;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012937 ctxt->type = (xmlSchemaTypePtr) decl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012938 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012939}
12940
Daniel Veillard4255d502002-04-16 15:50:10 +000012941/**
Daniel Veillardc0826a72004-08-10 14:17:33 +000012942 * xmlSchemaValidateAnyInternal:
12943 * @ctxt: a schema validation context
12944 * @node: the top node.
12945 *
12946 * Represents the recursive portion of xmlSchemaValidateAny. Not
12947 * intended to be used by other functions.
12948 *
12949 * Returns 0 if the element is valid, a positive error code
12950 * number otherwise and -1 in case of an internal error.
12951 */
12952static int
12953xmlSchemaValidateAnyInternal(xmlSchemaValidCtxtPtr ctxt,
12954 xmlSchemaWildcardPtr wild,
12955 xmlNodePtr node)
12956{
12957 const xmlChar *uri;
12958 int ret = 0;
12959 xmlNodePtr child;
12960
12961 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
12962 xmlSchemaElementPtr decl = NULL;
12963
12964 if (node->ns != NULL)
12965 decl = xmlHashLookup3(ctxt->schema->elemDecl,
12966 node->name, node->ns->href, NULL);
12967 else
12968 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
12969 if (decl != NULL) {
12970 ctxt->node = node;
12971 ctxt->type = (xmlSchemaTypePtr) decl;
12972 ret = xmlSchemaValidateElementType(ctxt, node->parent);
12973 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012974 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012975 "Internal error: xmlSchemaValidateAnyInternal, "
12976 "validating an element in the context of a wildcard.",
12977 NULL, NULL);
12978 } else if (ret > 0)
12979 return (ret);
12980 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
12981 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012982 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
12983 node, wild, "Global declaration is absent");
Daniel Veillardc0826a72004-08-10 14:17:33 +000012984 return (ctxt->err);
12985 }
12986 }
12987 if (node->children != NULL) {
12988 child = node->children;
12989 do {
12990 if (child->type == XML_ELEMENT_NODE) {
12991 if (child->ns != NULL)
12992 uri = child->ns->href;
12993 else
12994 uri = NULL;
12995 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012996 /* TODO: error code. */
12997 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012998 child, wild,
12999 "The namespace of the element is not allowed.");
13000 return (ctxt->err);
13001 }
13002 ret = xmlSchemaValidateAnyInternal(ctxt, wild, child);
13003 if (ret != 0)
13004 return (ret);
13005 }
13006 child = child->next;
13007 } while (child != NULL);
13008 }
13009 return (0);
13010}
13011
13012/**
13013 * xmlSchemaValidateAny:
13014 * @ctxt: a schema validation context
13015 *
13016 * Returns 0 if the element is valid, a positive error code
13017 * number otherwise and -1 in case of an internal or API error.
13018 */
13019static int
13020xmlSchemaValidateAny(xmlSchemaValidCtxtPtr ctxt)
13021{
13022 return(xmlSchemaValidateAnyInternal(ctxt,
13023 ctxt->type->attributeWildcard, ctxt->cur));
13024}
13025
13026/**
William M. Brack2f2a6632004-08-20 23:09:47 +000013027 * xmlSchemaValidateAnyTypeContent:
13028 * @ctxt: a schema validation context
13029 * @node: the current element
13030 *
13031 * This one validates the content of an element of the type
13032 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
13033 * thus elements in the subtree will be validated, if a corresponding
13034 * declaration in the schema exists.
13035 *
13036 * Returns 0 if the element and its subtree is valid, a positive error code
13037 * otherwise and -1 in case of an internal or API error.
13038 */
13039static int
13040xmlSchemaValidateAnyTypeContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13041{
13042 xmlNodePtr top = node;
13043 xmlSchemaTypePtr decl;
13044 int skipContent, ret;
13045
13046 if (node->children == NULL)
13047 return (0);
13048 node = node->children;
13049 while (node != NULL) {
13050 skipContent = 0;
13051 if (node->type == XML_ELEMENT_NODE) {
13052 /*
13053 * The process contents of the wildcard is "lax", thus
13054 * we need to validate the element if a declaration
13055 * exists.
13056 */
13057 if (node->ns != NULL)
13058 decl = xmlHashLookup3(ctxt->schema->elemDecl,
13059 node->name, node->ns->href, NULL);
13060 else
13061 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13062
13063 if (decl != NULL) {
13064 ctxt->node = node;
13065 ctxt->type = (xmlSchemaTypePtr) decl;
13066 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13067 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013068 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013069 "Internal error: xmlSchemaValidateAnyTypeContent, "
13070 "validating an element in the context of a wildcard.",
13071 NULL, NULL);
13072 return (ret);
13073 } else if (ret > 0)
13074 return (ret);
13075 skipContent = 1;
13076 }
13077 }
13078 /*
13079 * Browse the full subtree, deep first.
13080 */
13081 if ((skipContent == 0) && (node->children != NULL)) {
13082 /* deep first */
13083 node = node->children;
13084 } else if ((node != top) && (node->next != NULL)) {
13085 /* then siblings */
13086 node = node->next;
13087 } else if (node != top) {
13088 /* go up to parents->next if needed */
13089 while (node != top) {
13090 if (node->parent != NULL)
13091 node = node->parent;
13092 if ((node != top) && (node->next != NULL)) {
13093 node = node->next;
13094 break;
13095 }
13096 if (node->parent == NULL) {
13097 node = NULL;
13098 break;
13099 }
13100 }
13101 /* exit condition */
13102 if (node == top)
13103 node = NULL;
13104 } else
13105 break;
13106 }
13107 return (0);
13108}
13109
13110/**
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013111 * xmlSchemaHasElemOrCharContent:
13112 * @node: the node
13113 *
13114 * Scours the content of the given node for element
13115 * and character nodes.
13116 *
13117 * Returns 1 if an element or character node is found,
13118 * 0 otherwise.
13119 */
13120static int
13121xmlSchemaHasElemOrCharContent(xmlNodePtr node)
13122{
13123 xmlNodePtr cur;
13124
13125 if (node == NULL)
13126 return (0);
13127 cur = node->children;
13128 while (cur != NULL) {
13129 if ((cur->type == XML_ELEMENT_NODE) ||
13130 /*
13131 * TODO: Ask Daniel if these are all character nodes.
13132 */
13133 (cur->type == XML_TEXT_NODE) ||
13134 (cur->type == XML_CDATA_SECTION_NODE) ||
13135 /*
13136 * TODO: How XML_ENTITY_NODEs evaluated?
13137 */
13138 (cur->type == XML_ENTITY_REF_NODE) ||
13139 (cur->type == XML_ENTITY_NODE)) {
13140 return (1);
13141 }
13142 cur = cur->next;
13143 }
13144 return (0);
13145}
13146
13147/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013148 * xmlSchemaValidateComplexType:
13149 * @ctxt: a schema validation context
13150 * @node: the top node.
13151 *
13152 * Validate the content of an element expected to be a complex type type
13153 * xmlschema-1.html#cvc-complex-type
13154 * Validation Rule: Element Locally Valid (Complex Type)
13155 *
13156 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000013157 * number otherwise and -1 in case of internal or API error.
13158 * Note on reported errors: Although it might be nice to report
13159 * the name of the simple/complex type, used to validate the content
13160 * of a node, it is quite unnecessary: for global defined types
13161 * the local name of the element is equal to the NCName of the type,
13162 * for local defined types it makes no sense to output the internal
13163 * computed name of the type. TODO: Instead, one should attach the
13164 * struct of the type involved to the error handler - this allows
13165 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000013166 */
13167static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013168xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13169{
Daniel Veillard4255d502002-04-16 15:50:10 +000013170 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 xmlSchemaTypePtr type;
13172 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000013173 const xmlChar *nsUri;
Daniel Veillard3646d642004-06-02 19:19:14 +000013174
Daniel Veillard4255d502002-04-16 15:50:10 +000013175 child = ctxt->node;
13176 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013177 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013178
Daniel Veillard4255d502002-04-16 15:50:10 +000013179 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013180 case XML_SCHEMA_CONTENT_EMPTY: {
13181 /*
13182 * 1 If the {content type} is empty, then the element information
13183 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000013184 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 /*
13186 * TODO: Is the entity stuff correct?
13187 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013188 if (xmlSchemaHasElemOrCharContent(node) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013189 xmlSchemaVComplexTypeErr(ctxt,
13190 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
13191 node, type,
13192 "Character or element content is not allowed, "
13193 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013194 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013195 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013196 }
13197 case XML_SCHEMA_CONTENT_ELEMENTS:
13198 case XML_SCHEMA_CONTENT_MIXED:
13199 while (child != NULL) {
13200 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013201 if (child->ns != NULL)
13202 nsUri = child->ns->href;
13203 else
13204 nsUri = NULL;
13205 ret = xmlRegExecPushString2(ctxt->regexp,
13206 child->name, nsUri, child);
13207#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000013208 if (ret < 0)
13209 xmlGenericError(xmlGenericErrorContext,
13210 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000013211 else
13212 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013213 " --> %s\n", child->name);
13214#endif
13215 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
13216 /*
13217 * TODO: Ask Daniel if this are all character nodes.
13218 */
13219 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
13220 (child->type == XML_ENTITY_NODE) ||
13221 (child->type == XML_ENTITY_REF_NODE) ||
13222 (child->type == XML_CDATA_SECTION_NODE))) {
13223 /*
13224 * 2.3 If the {content type} is element-only, then the
13225 * element information item has no character information
13226 * item [children] other than those whose [character
13227 * code] is defined as a white space in [XML 1.0 (Second
13228 * Edition)].
13229 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013230 xmlSchemaVComplexTypeErr(ctxt,
13231 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
13232 node, type,
13233 "Character content is not allowed, "
13234 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013235 break;
13236 }
13237 child = child->next;
13238 }
13239 break;
13240 case XML_SCHEMA_CONTENT_SIMPLE:
13241 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013242 xmlChar *value = NULL;
13243 /*
13244 * We hit a complexType with a simpleContent resolving
13245 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000013246 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013247 /*
13248 * 2.2 If the {content type} is a simple type definition,
13249 * then the element information item has no element
13250 * information item [children], and the ·normalized value·
13251 * of the element information item is ·valid· with respect
13252 * to that simple type definition as defined by String
13253 * Valid (§3.14.4).
13254 */
13255 child = node->children;
13256 while (child != NULL) {
13257 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013258 xmlSchemaVComplexTypeErr(ctxt,
13259 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13260 node, type,
13261 "Element content is not allowed, because "
13262 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013263 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13264 break;
13265 }
13266 child = child->next;
13267 }
13268 if (ret == 0) {
13269 /*
13270 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000013271 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013272 if (ctxt->node == NULL)
13273 value = NULL;
13274 else
13275 value = xmlNodeGetContent(node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013276 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013277 if (ret > 0) {
13278 /*
13279 * NOTE: Although an error will be reported by
13280 * xmlSchemaValidateSimpleTypeValue, the spec wants
13281 * a specific complex type error to be reported
13282 * additionally.
13283 */
13284 xmlSchemaVComplexTypeErr(ctxt,
13285 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13286 node, type,
13287 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013288 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13289 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013290 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013292 "Element '%s': Error while validating character "
13293 "content against complex type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013294 node->name, type->name);
13295 return (-1);
13296 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013297 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013298 if (ret == 0) {
13299 /*
13300 * Apply facets of the complexType. Be sure to pass the
13301 * built-in type to xmlSchemaValidateFacetsInternal.
13302 */
13303 /* TODO: I don't know yet if the facets of the simple type
13304 * are used, or if the facets, defined by this complex type,
13305 * are to be used only. This here applies both facet sets.
13306 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013307
13308 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13309 value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013310 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013311 xmlSchemaVComplexTypeErr(ctxt,
13312 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13313 node, type,
13314 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013315 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13316 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013317 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013318 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013319 "Element '%s': Error while validating character "
13320 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013321 "apply facets.\n",
13322 type->name, NULL);
13323 }
13324 }
13325 if (value != NULL)
13326 xmlFree(value);
13327 /* TODO: facets */
13328 break;
13329 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013330 default:
13331 TODO xmlGenericError(xmlGenericErrorContext,
13332 "unimplemented content type %d\n",
13333 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000013334 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013336 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013337}
13338
13339/**
13340 * xmlSchemaValidateContent:
13341 * @ctxt: a schema validation context
13342 * @elem: an element
13343 * @type: the type declaration
13344 *
13345 * Validate the content of an element against the type.
13346 *
13347 * Returns 0 if the element is schemas valid, a positive error code
13348 * number otherwise and -1 in case of internal or API error.
13349 */
13350static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013351xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13352{
Daniel Veillard4255d502002-04-16 15:50:10 +000013353 xmlSchemaTypePtr type;
13354
Daniel Veillard4255d502002-04-16 15:50:10 +000013355 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013356 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013357
13358 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013359 case XML_SCHEMA_TYPE_ANY:
Daniel Veillardc0826a72004-08-10 14:17:33 +000013360 xmlSchemaValidateAny(ctxt);
13361 ctxt->type = type;
13362 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013363 case XML_SCHEMA_TYPE_COMPLEX:
13364 xmlSchemaValidateComplexType(ctxt, node);
13365 break;
13366 case XML_SCHEMA_TYPE_ELEMENT:{
13367 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
13368
13369 /*
13370 * Handle element reference here
13371 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013372 /*
13373 * TODO: This should be removed, since checks for
13374 * consistence should not be done during validation.
13375 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013376 if (decl->ref != NULL) {
13377 if (decl->refDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013378 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013379 "Internal error: element reference %s "
13380 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013381 return (-1);
13382 }
13383 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
13384 decl = decl->refDecl;
13385 }
William M. Bracke7091952004-05-11 15:09:58 +000013386 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013387 xmlSchemaValidateElementType(ctxt, node);
13388 ctxt->type = type;
13389 break;
13390 }
13391 case XML_SCHEMA_TYPE_BASIC:
William M. Brack2f2a6632004-08-20 23:09:47 +000013392 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
13393 xmlSchemaValidateAnyTypeContent(ctxt, node);
13394 else
13395 xmlSchemaValidateSimpleTypeElement(ctxt, node);
13396 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013397 case XML_SCHEMA_TYPE_SIMPLE:
13398 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013399 break;
13400 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013402 case XML_SCHEMA_TYPE_SEQUENCE:
13403 TODO break;
13404 case XML_SCHEMA_TYPE_CHOICE:
13405 TODO break;
13406 case XML_SCHEMA_TYPE_ALL:
13407 TODO break;
13408 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13409 TODO break;
13410 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13411 TODO break;
13412 case XML_SCHEMA_TYPE_UR:
13413 TODO break;
13414 case XML_SCHEMA_TYPE_RESTRICTION:
13415 /*xmlSchemaValidateRestrictionType(ctxt, node); */
13416 TODO break;
13417 case XML_SCHEMA_TYPE_EXTENSION:
13418 TODO break;
13419 case XML_SCHEMA_TYPE_ATTRIBUTE:
13420 TODO break;
13421 case XML_SCHEMA_TYPE_GROUP:
13422 TODO break;
13423 case XML_SCHEMA_TYPE_NOTATION:
13424 TODO break;
13425 case XML_SCHEMA_TYPE_LIST:
13426 TODO break;
13427 case XML_SCHEMA_TYPE_UNION:
13428 TODO break;
13429 case XML_SCHEMA_FACET_MININCLUSIVE:
13430 TODO break;
13431 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13432 TODO break;
13433 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13434 TODO break;
13435 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13436 TODO break;
13437 case XML_SCHEMA_FACET_TOTALDIGITS:
13438 TODO break;
13439 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13440 TODO break;
13441 case XML_SCHEMA_FACET_PATTERN:
13442 TODO break;
13443 case XML_SCHEMA_FACET_ENUMERATION:
13444 TODO break;
13445 case XML_SCHEMA_FACET_WHITESPACE:
13446 TODO break;
13447 case XML_SCHEMA_FACET_LENGTH:
13448 TODO break;
13449 case XML_SCHEMA_FACET_MAXLENGTH:
13450 TODO break;
13451 case XML_SCHEMA_FACET_MINLENGTH:
13452 TODO break;
13453 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13454 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000013455 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
13456 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000013457 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013458
13459 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013460 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013461 ctxt->node = ctxt->node->next;
13462 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013463 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013464}
13465
13466/**
13467 * xmlSchemaValidateType:
13468 * @ctxt: a schema validation context
13469 * @elem: an element
13470 * @type: the list of type declarations
13471 *
13472 * Validate the content of an element against the types.
13473 *
13474 * Returns 0 if the element is schemas valid, a positive error code
13475 * number otherwise and -1 in case of internal or API error.
13476 */
13477static int
13478xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013479 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
13480{
Daniel Veillard4255d502002-04-16 15:50:10 +000013481 xmlChar *nil;
13482
Daniel Veillard2db8c122003-07-08 12:16:59 +000013483 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013484 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000013485
Daniel Veillard3646d642004-06-02 19:19:14 +000013486 /* This one is called by "xmlSchemaValidateElementType" and
13487 * "xmlSchemaValidateElement".
13488 */
13489
Daniel Veillard4255d502002-04-16 15:50:10 +000013490 /*
13491 * 3.3.4 : 2
13492 */
13493 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013494 xmlSchemaVCustomErr(ctxt,
13495 XML_SCHEMAV_CVC_ELT_2,
13496 elem, NULL,
13497 "The element declaration is abstract", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013498 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013499 }
13500 /*
13501 * 3.3.4: 3
13502 */
13503 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
13504 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013505 /* 3.3.4: 3.2 */
13506 if (xmlStrEqual(nil, BAD_CAST "true")) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013507 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
13508 xmlSchemaVCustomErr(ctxt,
13509 XML_SCHEMAV_CVC_ELT_3_2_1,
13510 /* XML_SCHEMAS_ERR_NOTEMPTY, */
13511 elem, NULL,
13512 "The 'nilled' element must have no character or element "
13513 "content", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013514 return (ctxt->err);
13515 }
13516 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
13517 (elemDecl->value != NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013518 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
13519 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
13520 elem, NULL,
13521 "There is a fixed value constraint defined for "
13522 "the 'nilled' element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013523 return (ctxt->err);
13524 }
13525 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013526 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013527 /* 3.3.4: 3.1 */
13528 if (nil != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013529 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_1,
13530 /* XML_SCHEMAS_ERR_NOTNILLABLE, */
13531 elem, NULL,
13532 "The element is not 'nillable'", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013533 xmlFree(nil);
13534 return (ctxt->err);
13535 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013536 }
13537
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013538 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000013539
13540 ctxt->type = elemDecl->subtypes;
13541 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013542 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013543 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013544}
13545
13546
13547/**
13548 * xmlSchemaValidateAttributes:
13549 * @ctxt: a schema validation context
13550 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000013551 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000013552 *
13553 * Validate the attributes of an element.
13554 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013555 * 1. Existent, invalid attributes are reported in the form
13556 * "prefix:localName".
13557 * Reason: readability - it is easier to find the actual XML
13558 * representation of the attributes QName.
13559 * 2. Missing attributes are reported in the form
13560 * {"URI", "localName"}.
13561 * This is necessary, since the the prefix need not to be declared
13562 * at all, and thus is not computable.
13563 *
Daniel Veillard4255d502002-04-16 15:50:10 +000013564 * Returns 0 if the element is schemas valid, a positive error code
13565 * number otherwise and -1 in case of internal or API error.
13566 */
13567static int
Daniel Veillard3646d642004-06-02 19:19:14 +000013568xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013569{
Daniel Veillard3646d642004-06-02 19:19:14 +000013570 int ret;
13571 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013572 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013573 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000013574 xmlSchemaAttributeLinkPtr attrUse;
13575 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013576 int found;
William M. Brack803812b2004-06-03 02:11:24 +000013577 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013578#ifdef DEBUG_ATTR_VALIDATION
13579 int redundant = 0;
13580#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013581
Daniel Veillardc0826a72004-08-10 14:17:33 +000013582 /*
13583 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
13584 * if we have an attribute reference or an attribute declaration.
13585 */
13586 /*
13587 * Allow all attributes if the type is anyType.
13588 */
13589 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
13590 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013591 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013593 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000013594 attrDecl = attrUse->attr;
13595#ifdef DEBUG_ATTR_VALIDATION
13596 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
13597 printf("attr use - use: %d\n", attrDecl->occurs);
13598#endif
13599 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
13600
13601 if (curState->decl == attrUse->attr) {
13602#ifdef DEBUG_ATTR_VALIDATION
13603 redundant = 1;
13604#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013605 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013606 attr = curState->attr;
13607#ifdef DEBUG_ATTR_VALIDATION
13608 printf("attr - name: %s\n", attr->name);
13609 if (attr->ns != NULL)
13610 printf("attr - ns: %s\n", attr->ns->href);
13611 else
13612 printf("attr - ns: none\n");
13613#endif
13614 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013615 if (attr == NULL)
13616 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013617 if (attrDecl->ref != NULL) {
13618 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013619 continue;
13620 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013621 if ((attrDecl->refNs == NULL) ||
13622 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013623 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013624 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013625 continue;
13626 }
13627 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013628 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013629 continue;
13630 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013631 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013632 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013633 if (attr->ns == NULL) {
13634 /*
William M. Bracke7091952004-05-11 15:09:58 +000013635 * accept an unqualified attribute only if the target
13636 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013637 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013638 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000013639 /*
13640 * This check was removed, since the target namespace
13641 * was evaluated during parsing and already took
13642 * "attributeFormDefault" into account.
13643 */
13644 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013645 continue;
13646 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013647 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013648 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013649 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013650 attr->ns->href))
13651 continue;
13652 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013653 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013654#ifdef DEBUG_ATTR_VALIDATION
13655 printf("found\n");
13656#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013657 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000013658 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013659 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013660
Daniel Veillard3646d642004-06-02 19:19:14 +000013661 if (attrDecl->subtypes == NULL) {
13662 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
13663 curState->decl = attrDecl;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013664 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013665 "Internal error: attribute %s type not resolved\n",
13666 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013667 continue;
13668 }
13669 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013670 ctxt->type = attrDecl->subtypes;
13671 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013672 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000013673 if (ret != 0)
13674 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13675 else
13676 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13677 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013678 if (value != NULL) {
13679 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000013680 }
13681 }
13682 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
13683 xmlSchemaAttrStatePtr tmp;
13684
13685#ifdef DEBUG_ATTR_VALIDATION
13686 printf("required attr not found\n");
13687#endif
13688 /*
13689 * Add a new dummy attribute state.
13690 */
13691 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
13692 if (tmp == NULL) {
13693 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
13694 return (-1);
13695 }
13696 tmp->attr = NULL;
13697 tmp->state = XML_SCHEMAS_ATTR_MISSING;
13698 tmp->decl = attrDecl;
13699 tmp->next = NULL;
13700
13701 if (reqAttrStates == NULL) {
13702 reqAttrStates = tmp;
13703 reqAttrStatesTop = tmp;
13704 } else {
13705 reqAttrStatesTop->next = tmp;
13706 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013707 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013708
13709 }
13710 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013711 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013712 /*
13713 * Add required attributes to the attribute states of the context.
13714 */
13715 if (reqAttrStates != NULL) {
13716 if (ctxt->attr == NULL) {
13717 ctxt->attr = reqAttrStates;
13718 } else {
13719 ctxt->attrTop->next = reqAttrStates;
13720 }
13721 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013722 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013723 /*
13724 * Process wildcards.
13725 */
13726 if (type->attributeWildcard != NULL) {
13727#ifdef DEBUG_ATTR_VALIDATION
13728 xmlSchemaWildcardNsPtr ns;
13729 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013730 if (type->attributeWildcard->processContents ==
13731 XML_SCHEMAS_ANY_LAX)
13732 printf("processContents: lax\n");
13733 else if (type->attributeWildcard->processContents ==
13734 XML_SCHEMAS_ANY_STRICT)
13735 printf("processContents: strict\n");
13736 else
13737 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000013738 if (type->attributeWildcard->any)
13739 printf("type: any\n");
13740 else if (type->attributeWildcard->negNsSet != NULL) {
13741 printf("type: negated\n");
13742 if (type->attributeWildcard->negNsSet->value == NULL)
13743 printf("ns: (absent)\n");
13744 else
13745 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
13746 } else if (type->attributeWildcard->nsSet != NULL) {
13747 printf("type: set\n");
13748 ns = type->attributeWildcard->nsSet;
13749 while (ns != NULL) {
13750 if (ns->value == NULL)
13751 printf("ns: (absent)\n");
13752 else
13753 printf("ns: %s\n", ns->value);
13754 ns = ns->next;
13755 }
13756 } else
13757 printf("empty\n");
13758
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013759
13760#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 curState = ctxt->attr;
13762 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013763 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
13764 if (curState->attr->ns != NULL)
13765 nsURI = curState->attr->ns->href;
13766 else
13767 nsURI = NULL;
13768 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
13769 nsURI)) {
13770 /*
13771 * Handle processContents.
13772 */
13773 if ((type->attributeWildcard->processContents ==
13774 XML_SCHEMAS_ANY_LAX) ||
13775 (type->attributeWildcard->processContents ==
13776 XML_SCHEMAS_ANY_STRICT)) {
13777
13778 attr = curState->attr;
13779 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
13780 attr->name, nsURI);
13781 if (attrDecl != NULL) {
13782 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013783 ctxt->cur = (xmlNodePtr) attr;
13784 ctxt->node = attr->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 ctxt->type = attrDecl->subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013788 if (ret != 0)
13789 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13790 else
13791 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13792 curState->decl = attrDecl;
13793 if (value != NULL) {
13794 xmlFree(value);
13795 }
13796
13797 } else if (type->attributeWildcard->processContents ==
13798 XML_SCHEMAS_ANY_LAX) {
13799 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13800 }
13801 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000013802 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013803 }
13804 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013805 curState = curState->next;
13806 }
13807 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 /*
13809 * Report missing and illegal attributes.
13810 */
13811 if (ctxt->attr != NULL) {
13812 curState = ctxt->attr;
13813 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
13814 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
13815 attr = curState->attr;
13816 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
13817 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013818 else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
13819 /* TODO: "prohibited" won't ever be touched here!.
13820 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
13821 */
13822 if (type->attributeWildcard == NULL) {
13823 xmlSchemaVIllegalAttrErr(ctxt,
13824 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
13825 } else {
13826 xmlSchemaVIllegalAttrErr(ctxt,
13827 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
13828 }
13829 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013830 }
13831 curState = curState->next;
13832 }
13833 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013834#ifdef DEBUG_ATTR_VALIDATION
13835 if (redundant)
13836 xmlGenericError(xmlGenericErrorContext,
13837 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
13838 type->name);
13839#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013840 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013841}
13842
13843/**
13844 * xmlSchemaValidateElement:
13845 * @ctxt: a schema validation context
13846 * @elem: an element
13847 *
13848 * Validate an element in a tree
13849 *
13850 * Returns 0 if the element is schemas valid, a positive error code
13851 * number otherwise and -1 in case of internal or API error.
13852 */
13853static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013854xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
13855{
Daniel Veillard4255d502002-04-16 15:50:10 +000013856 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000013857 int ret;
13858 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013859
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013860 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013861 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13862 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013863 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013864 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13865 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013866 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013867 /*
13868 * This one is called by xmlSchemaValidateDocument and
13869 * xmlSchemaValidateAnyInernal.
13870 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013871
Daniel Veillard4255d502002-04-16 15:50:10 +000013872 /*
13873 * 3.3.4 : 1
13874 */
13875 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013876 xmlSchemaVCustomErr(ctxt,
13877 XML_SCHEMAV_CVC_ELT_1,
13878 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
13879 elem, NULL,
13880 "Global declaration is absent", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013881 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013882 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013883 /* TODO: This should be already catched at the schema parsing level. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013884 if (elemDecl->subtypes == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013885 xmlSchemaVCustomErr(ctxt,
13886 XML_SCHEMAV_INTERNAL,
13887 /* XML_SCHEMAS_ERR_NOTYPE */
13888 elem, NULL,
13889 "The element declaration has no type assigned", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013890 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013891 }
13892 /*
13893 * Verify the attributes
13894 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013895 attrs = ctxt->attr;
13896 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013897 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013898 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->subtypes);
13899 if (ctxt->attr != NULL)
13900 xmlSchemaFreeAttributeStates(ctxt->attr);
13901 ctxt->attr = attrs;
13902 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013903 /*
13904 * Verify the element content recursively
13905 */
13906 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013907 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
13908 (xmlRegExecCallbacks)
13909 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013910#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013911 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013912#endif
13913 }
13914 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013915 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013916 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013917#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013918 xmlGenericError(xmlGenericErrorContext,
13919 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013920#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000013921 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013922 /* TODO: error code. */
13923 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13924 elem, elemDecl->subtypes,
13925 "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013926 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013927 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13928 elem, elemDecl->subtypes,
13929 "The element content is not valid", NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013930#ifdef DEBUG_CONTENT
Daniel Veillardc0826a72004-08-10 14:17:33 +000013931 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013932 xmlGenericError(xmlGenericErrorContext,
13933 "Element %s content check succeeded\n",
13934 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013935
13936#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013937 }
13938 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000013939 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013940 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013941}
13942
13943/**
13944 * xmlSchemaValidateDocument:
13945 * @ctxt: a schema validation context
13946 * @doc: a parsed document tree
13947 *
13948 * Validate a document tree in memory.
13949 *
13950 * Returns 0 if the document is schemas valid, a positive error code
13951 * number otherwise and -1 in case of internal or API error.
13952 */
13953static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013954xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
13955{
Daniel Veillard4255d502002-04-16 15:50:10 +000013956 xmlNodePtr root;
13957 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958
Daniel Veillard4255d502002-04-16 15:50:10 +000013959 root = xmlDocGetRootElement(doc);
13960 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013961 xmlSchemaVCustomErr(ctxt,
13962 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
13963 (xmlNodePtr) doc, NULL,
13964 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013965 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013966 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013967
Daniel Veillard4255d502002-04-16 15:50:10 +000013968 if (root->ns != NULL)
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013969 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, root->ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +000013970 else
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013971 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013972 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013973 xmlSchemaVCustomErr(ctxt,
13974 XML_SCHEMAV_CVC_ELT_1,
13975 root, NULL,
13976 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
13977 "Global declaration is absent", NULL);
13978 }
13979 /*
13980 * Removed, since xmlSchemaGetElem will return global declarations only.
13981 *
13982 else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000013983 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000013984 "Root element %s not global\n", root->name, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013985 }
13986 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013987 /*
13988 * Okay, start the recursive validation
13989 */
13990 xmlSchemaValidateElement(ctxt, root);
13991
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013992 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013993}
13994
13995/************************************************************************
13996 * *
13997 * SAX Validation code *
13998 * *
13999 ************************************************************************/
14000
14001/************************************************************************
14002 * *
14003 * Validation interfaces *
14004 * *
14005 ************************************************************************/
14006
14007/**
14008 * xmlSchemaNewValidCtxt:
14009 * @schema: a precompiled XML Schemas
14010 *
14011 * Create an XML Schemas validation context based on the given schema
14012 *
14013 * Returns the validation context or NULL in case of error
14014 */
14015xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014016xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
14017{
Daniel Veillard4255d502002-04-16 15:50:10 +000014018 xmlSchemaValidCtxtPtr ret;
14019
14020 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
14021 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014022 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014023 return (NULL);
14024 }
14025 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014026 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000014027 ret->attrTop = NULL;
14028 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014029 return (ret);
14030}
14031
14032/**
14033 * xmlSchemaFreeValidCtxt:
14034 * @ctxt: the schema validation context
14035 *
14036 * Free the resources associated to the schema validation context
14037 */
14038void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014039xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
14040{
Daniel Veillard4255d502002-04-16 15:50:10 +000014041 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014042 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014043 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014044 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000014045 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014046 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000014047 xmlFree(ctxt);
14048}
14049
14050/**
14051 * xmlSchemaSetValidErrors:
14052 * @ctxt: a schema validation context
14053 * @err: the error function
14054 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000014055 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000014056 *
William M. Brack2f2a6632004-08-20 23:09:47 +000014057 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000014058 */
14059void
14060xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014061 xmlSchemaValidityErrorFunc err,
14062 xmlSchemaValidityWarningFunc warn, void *ctx)
14063{
Daniel Veillard4255d502002-04-16 15:50:10 +000014064 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014065 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014066 ctxt->error = err;
14067 ctxt->warning = warn;
14068 ctxt->userData = ctx;
14069}
14070
14071/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014072 * xmlSchemaGetValidErrors:
14073 * @ctxt: a XML-Schema validation context
14074 * @err: the error function result
14075 * @warn: the warning function result
14076 * @ctx: the functions context result
14077 *
14078 * Get the error and warning callback informations
14079 *
14080 * Returns -1 in case of error and 0 otherwise
14081 */
14082int
14083xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
14084 xmlSchemaValidityErrorFunc * err,
14085 xmlSchemaValidityWarningFunc * warn, void **ctx)
14086{
14087 if (ctxt == NULL)
14088 return (-1);
14089 if (err != NULL)
14090 *err = ctxt->error;
14091 if (warn != NULL)
14092 *warn = ctxt->warning;
14093 if (ctx != NULL)
14094 *ctx = ctxt->userData;
14095 return (0);
14096}
14097
14098/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014099 * xmlSchemaValidateDoc:
14100 * @ctxt: a schema validation context
14101 * @doc: a parsed document tree
14102 *
14103 * Validate a document tree in memory.
14104 *
14105 * Returns 0 if the document is schemas valid, a positive error code
14106 * number otherwise and -1 in case of internal or API error.
14107 */
14108int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014109xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14110{
Daniel Veillard4255d502002-04-16 15:50:10 +000014111 int ret;
14112
14113 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014114 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014115
14116 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000014117 ctxt->err = 0;
14118 ctxt->nberrors = 0;
14119
Daniel Veillard4255d502002-04-16 15:50:10 +000014120 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014121 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000014122}
14123
14124/**
14125 * xmlSchemaValidateStream:
14126 * @ctxt: a schema validation context
14127 * @input: the input to use for reading the data
14128 * @enc: an optional encoding information
14129 * @sax: a SAX handler for the resulting events
14130 * @user_data: the context to provide to the SAX handler.
14131 *
14132 * Validate a document tree in memory.
14133 *
14134 * Returns 0 if the document is schemas valid, a positive error code
14135 * number otherwise and -1 in case of internal or API error.
14136 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014137int
Daniel Veillard4255d502002-04-16 15:50:10 +000014138xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014139 xmlParserInputBufferPtr input, xmlCharEncoding enc,
14140 xmlSAXHandlerPtr sax, void *user_data)
14141{
Daniel Veillard4255d502002-04-16 15:50:10 +000014142 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014143 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014144 ctxt->input = input;
14145 ctxt->enc = enc;
14146 ctxt->sax = sax;
14147 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014148 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014149}
14150
14151#endif /* LIBXML_SCHEMAS_ENABLED */