blob: 75bb983eba5039fcf6ee62d34bc33868cf8c733a [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
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003447xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3448{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003449 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003450 int ret = 0;
3451
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003452 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003453 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003454 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003455
3456 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003457 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003458 }
3459
3460 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003461 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003462 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003463 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003464 ret = ret * 10 + (*cur - '0');
3465 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003466 }
William M. Brack76e95df2003-10-18 16:20:14 +00003467 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003468 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003470 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003471 "The value '%s' of the attribute 'maxOccurs' is invalid.\n",
3472 val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003473 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003474 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003476}
3477
3478/**
3479 * xmlGetMinOccurs:
3480 * @ctxt: a schema validation context
3481 * @node: a subtree containing XML Schema informations
3482 *
3483 * Get the minOccurs property
3484 *
3485 * Returns the default if not found, or the value
3486 */
3487static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003488xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3489{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003490 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 int ret = 0;
3492
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003493 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003496
3497 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003498 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003500 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501 ret = ret * 10 + (*cur - '0');
3502 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003503 }
William M. Brack76e95df2003-10-18 16:20:14 +00003504 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003505 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003506 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003507 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3508 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003510 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003511 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003512}
3513
3514/**
3515 * xmlGetBooleanProp:
3516 * @ctxt: a schema validation context
3517 * @node: a subtree containing XML Schema informations
3518 * @name: the attribute name
3519 * @def: the default value
3520 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003521 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003522 *
3523 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003524 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003525 */
3526static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003527xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3528 xmlChar **ownerDes,
3529 xmlSchemaTypePtr ownerItem,
3530 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003531 const char *name, int def)
3532{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003533 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003534
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003535 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003536 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003538 /*
3539 * 3.2.2.1 Lexical representation
3540 * An instance of a datatype that is defined as ·boolean·
3541 * can have the following legal literals {true, false, 1, 0}.
3542 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003543 if (xmlStrEqual(val, BAD_CAST "true"))
3544 def = 1;
3545 else if (xmlStrEqual(val, BAD_CAST "false"))
3546 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003547 else if (xmlStrEqual(val, BAD_CAST "1"))
3548 def = 1;
3549 else if (xmlStrEqual(val, BAD_CAST "0"))
3550 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003551 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003552 xmlSchemaPSimpleTypeErr(ctxt,
3553 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003554 ownerDes, ownerItem, node,
3555 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3556 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003558 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003559}
3560
3561/************************************************************************
3562 * *
3563 * Shema extraction from an Infoset *
3564 * *
3565 ************************************************************************/
3566static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3567 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003568 xmlNodePtr node,
3569 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003570static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3571 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003572 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003573 xmlNodePtr node,
3574 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003575static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3576 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003577 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003578 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003579static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3580 xmlSchemaPtr schema,
3581 xmlNodePtr node);
3582static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3583 xmlSchemaPtr schema,
3584 xmlNodePtr node);
3585static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3586 ctxt,
3587 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003588 xmlNodePtr node,
3589 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003590static xmlSchemaAttributeGroupPtr
3591xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003592 xmlSchemaPtr schema, xmlNodePtr node,
3593 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003594static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3595 xmlSchemaPtr schema,
3596 xmlNodePtr node);
3597static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3598 xmlSchemaPtr schema,
3599 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003600static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3602 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003603
3604/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003605 * xmlSchemaPValAttrNode:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003606 *
3607 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003608 * @ownerDes: the designation of the parent element
3609 * @ownerItem: the schema object owner if existent
3610 * @attr: the schema attribute node being validated
3611 * @value: the value
3612 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003613 *
3614 * Validates a value against the given built-in type.
3615 * This one is intended to be used internally for validation
3616 * of schema attribute values during parsing of the schema.
3617 *
3618 * Returns 0 if the value is valid, a positive error code
3619 * number otherwise and -1 in case of an internal or API error.
3620 */
3621static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003622xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3623 xmlChar **ownerDes,
3624 xmlSchemaTypePtr ownerItem,
3625 xmlAttrPtr attr,
3626 const xmlChar *value,
3627 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003628{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003629
Daniel Veillardc0826a72004-08-10 14:17:33 +00003630 int ret = 0;
3631
3632 /*
3633 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3634 * one is really meant to be used internally, so better not.
3635 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003636 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003637 return (-1);
3638 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3639 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003640 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003641 "Internal error: xmlSchemaPvalueAttrNode, the given "
3642 "type '%s' is not a built-in type.\n",
3643 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003644 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003645 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003646 switch (type->builtInType) {
3647 case XML_SCHEMAS_NCNAME:
3648 ret = xmlValidateNCName(value, 1);
3649 break;
3650 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003651 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003652 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003653 "Internal error: xmlSchemaPvalueAttrNode, use "
3654 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3655 "for extracting QName valueues instead.\n",
3656 NULL, NULL);
3657 return (-1);
3658 case XML_SCHEMAS_ANYURI:
3659 if (value != NULL) {
3660 xmlURIPtr uri = xmlParseURI((const char *) value);
3661 if (uri == NULL)
3662 ret = 1;
3663 else
3664 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003665 }
3666 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003667 case XML_SCHEMAS_TOKEN: {
3668 const xmlChar *cur = value;
3669
3670 if (IS_BLANK_CH(*cur)) {
3671 ret = 1;
3672 } else while (*cur != 0) {
3673 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3674 ret = 1;
3675 break;
3676 } else if (*cur == ' ') {
3677 cur++;
3678 if ((*cur == 0) || (*cur == ' ')) {
3679 ret = 1;
3680 break;
3681 }
3682 } else {
3683 cur++;
3684 }
3685 }
3686 }
3687 break;
3688 case XML_SCHEMAS_LANGUAGE:
3689 if (xmlCheckLanguageID(value) != 1)
3690 ret = 1;
3691 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003692 default: {
3693 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003694 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003695 "Internal error: xmlSchemaPvalueAttrNode, "
3696 "valueidation using the type '%s' is not implemented "
3697 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003698 type->name, NULL);
3699 return (-1);
3700 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003701 }
3702 /*
3703 * TODO: Should we use the S4S error codes instead?
3704 */
3705 if (ret > 0) {
3706 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3707 xmlSchemaPSimpleTypeErr(ctxt,
3708 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3709 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003710 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003711 NULL, NULL, NULL);
3712 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3713 } else {
3714 xmlSchemaPSimpleTypeErr(ctxt,
3715 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3716 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003717 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003718 NULL, NULL, NULL);
3719 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3720 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003721 }
3722 return (ret);
3723}
3724
3725/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003726 * xmlSchemaPValAttrNode:
3727 *
3728 * @ctxt: a schema parser context
3729 * @ownerDes: the designation of the parent element
3730 * @ownerItem: the schema object owner if existent
3731 * @attr: the schema attribute node being validated
3732 * @type: the built-in type to be validated against
3733 * @value: the resulting value if any
3734 *
3735 * Extracts and validates a value against the given built-in type.
3736 * This one is intended to be used internally for validation
3737 * of schema attribute values during parsing of the schema.
3738 *
3739 * Returns 0 if the value is valid, a positive error code
3740 * number otherwise and -1 in case of an internal or API error.
3741 */
3742static int
3743xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3744 xmlChar **ownerDes,
3745 xmlSchemaTypePtr ownerItem,
3746 xmlAttrPtr attr,
3747 xmlSchemaTypePtr type,
3748 const xmlChar **value)
3749{
3750 const xmlChar *val;
3751
3752 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3753 return (-1);
3754
3755 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3756 if (value != NULL)
3757 *value = val;
3758
3759 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3760 val, type));
3761}
3762
3763/**
3764 * xmlSchemaPValAttr:
3765 *
3766 * @ctxt: a schema parser context
3767 * @node: the element node of the attribute
3768 * @ownerDes: the designation of the parent element
3769 * @ownerItem: the schema object owner if existent
3770 * @ownerElem: the owner element node
3771 * @name: the name of the schema attribute node
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
3783xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3784 xmlChar **ownerDes,
3785 xmlSchemaTypePtr ownerItem,
3786 xmlNodePtr ownerElem,
3787 const char *name,
3788 xmlSchemaTypePtr type,
3789 const xmlChar **value)
3790{
3791 xmlAttrPtr attr;
3792
3793 if ((ctxt == NULL) || (type == NULL)) {
3794 if (value != NULL)
3795 *value = NULL;
3796 return (-1);
3797 }
3798 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3799 if (value != NULL)
3800 *value = NULL;
3801 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003802 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003803 "Internal error: xmlSchemaPValAttr, the given "
3804 "type '%s' is not a built-in type.\n",
3805 type->name, NULL);
3806 return (-1);
3807 }
3808 attr = xmlSchemaGetPropNode(ownerElem, name);
3809 if (attr == NULL) {
3810 if (value != NULL)
3811 *value = NULL;
3812 return (0);
3813 }
3814 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
3815 type, value));
3816}
3817/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003818 * xmlSchemaParseAttrDecls:
3819 * @ctxt: a schema validation context
3820 * @schema: the schema being built
3821 * @node: a subtree containing XML Schema informations
3822 * @type: the hosting type
3823 *
3824 * parse a XML schema attrDecls declaration corresponding to
3825 * <!ENTITY % attrDecls
3826 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
3827 */
3828static xmlNodePtr
3829xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3830 xmlNodePtr child, xmlSchemaTypePtr type)
3831{
3832 xmlSchemaAttributePtr lastattr, attr;
3833
3834 lastattr = NULL;
3835 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003836 (IS_SCHEMA(child, "attributeGroup"))) {
3837 attr = NULL;
3838 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003839 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003840 } else if (IS_SCHEMA(child, "attributeGroup")) {
3841 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003842 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003843 }
3844 if (attr != NULL) {
3845 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003846 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3847 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
3848 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003849 type->attributes = attr;
3850 lastattr = attr;
3851 } else {
3852 lastattr->next = attr;
3853 lastattr = attr;
3854 }
3855 }
3856 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003857 }
3858 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003859 xmlSchemaWildcardPtr wildcard;
3860
3861 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
3862 if (wildcard != NULL) {
3863 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3864 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
3865 else
3866 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003867 }
3868 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003869 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003870 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00003871}
3872
3873/**
3874 * xmlSchemaParseAnnotation:
3875 * @ctxt: a schema validation context
3876 * @schema: the schema being built
3877 * @node: a subtree containing XML Schema informations
3878 *
3879 * parse a XML schema Attrribute declaration
3880 * *WARNING* this interface is highly subject to change
3881 *
William M. Bracke7091952004-05-11 15:09:58 +00003882 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003883 * 1 in case of success.
3884 */
3885static xmlSchemaAnnotPtr
3886xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3887 xmlNodePtr node)
3888{
3889 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003890 xmlNodePtr child = NULL;
3891 xmlAttrPtr attr;
3892 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003893
Daniel Veillardc0826a72004-08-10 14:17:33 +00003894 /*
3895 * INFO: S4S completed.
3896 */
3897 /*
3898 * id = ID
3899 * {any attributes with non-schema namespace . . .}>
3900 * Content: (appinfo | documentation)*
3901 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003902 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3903 return (NULL);
3904 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003905 attr = node->properties;
3906 while (attr != NULL) {
3907 if (((attr->ns == NULL) &&
3908 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
3909 ((attr->ns != NULL) &&
3910 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
3911
3912 xmlSchemaPIllegalAttrErr(ctxt,
3913 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3914 NULL, NULL, attr);
3915 }
3916 attr = attr->next;
3917 }
3918 /* TODO: Check id. */
3919
3920 /*
3921 * And now for the children...
3922 */
3923 child = node->children;
3924 while (child != NULL) {
3925 if (IS_SCHEMA(child, "appinfo")) {
3926 /* TODO: make available the content of "appinfo". */
3927 /*
3928 * source = anyURI
3929 * {any attributes with non-schema namespace . . .}>
3930 * Content: ({any})*
3931 */
3932 attr = child->properties;
3933 while (attr != NULL) {
3934 if (((attr->ns == NULL) &&
3935 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
3936 ((attr->ns != NULL) &&
3937 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003938
Daniel Veillardc0826a72004-08-10 14:17:33 +00003939 xmlSchemaPIllegalAttrErr(ctxt,
3940 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3941 NULL, NULL, attr);
3942 }
3943 attr = attr->next;
3944 }
3945 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
3946 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
3947 child = child->next;
3948 } else if (IS_SCHEMA(child, "documentation")) {
3949 /* TODO: make available the content of "documentation". */
3950 /*
3951 * source = anyURI
3952 * {any attributes with non-schema namespace . . .}>
3953 * Content: ({any})*
3954 */
3955 attr = child->properties;
3956 while (attr != NULL) {
3957 if (attr->ns == NULL) {
3958 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
3959 xmlSchemaPIllegalAttrErr(ctxt,
3960 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3961 NULL, NULL, attr);
3962 }
3963 } else {
3964 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
3965 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
3966 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
3967
3968 xmlSchemaPIllegalAttrErr(ctxt,
3969 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3970 NULL, NULL, attr);
3971 }
3972 }
3973 attr = attr->next;
3974 }
3975 /*
3976 * Attribute "xml:lang".
3977 */
3978 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
3979 if (attr != NULL)
3980 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
3981 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
3982 child = child->next;
3983 } else {
3984 if (!barked)
3985 xmlSchemaPContentErr(ctxt,
3986 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3987 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
3988 barked = 1;
3989 child = child->next;
3990 }
3991 }
3992
Daniel Veillard4255d502002-04-16 15:50:10 +00003993 return (ret);
3994}
3995
3996/**
3997 * xmlSchemaParseFacet:
3998 * @ctxt: a schema validation context
3999 * @schema: the schema being built
4000 * @node: a subtree containing XML Schema informations
4001 *
4002 * parse a XML schema Facet declaration
4003 * *WARNING* this interface is highly subject to change
4004 *
4005 * Returns the new type structure or NULL in case of error
4006 */
4007static xmlSchemaFacetPtr
4008xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004009 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004010{
4011 xmlSchemaFacetPtr facet;
4012 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004013 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004014
4015 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4016 return (NULL);
4017
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004018 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019 if (facet == NULL) {
4020 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4021 return (NULL);
4022 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004023 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004024 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004025 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004026 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4027 "Facet %s has no value\n", node->name, NULL);
4028 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004029 return (NULL);
4030 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004031 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004033 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004034 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004035 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004036 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004037 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004038 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004039 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004040 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004041 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004042 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004043 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004044 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004045 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004046 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004047 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004048 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004049 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004050 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004051 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004052 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4053 } else if (IS_SCHEMA(node, "minLength")) {
4054 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4055 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4057 "Unknown facet type %s\n", node->name, NULL);
4058 xmlSchemaFreeFacet(facet);
4059 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004060 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004061 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004062 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004063 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4064 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4065 const xmlChar *fixed;
4066
4067 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4068 if (fixed != NULL) {
4069 if (xmlStrEqual(fixed, BAD_CAST "true"))
4070 facet->fixed = 1;
4071 }
4072 }
4073
Daniel Veillard4255d502002-04-16 15:50:10 +00004074 child = node->children;
4075
4076 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004077 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4078 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004079 }
4080 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004081 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4082 "Facet %s has unexpected child content\n",
4083 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004084 }
4085 return (facet);
4086}
4087
4088/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004089 * xmlSchemaParseWildcardNs:
4090 * @ctxt: a schema parser context
4091 * @wildc: the wildcard, already created
4092 * @node: a subtree containing XML Schema informations
4093 *
4094 * Parses the attribute "processContents" and "namespace"
4095 * of a xsd:anyAttribute and xsd:any.
4096 * *WARNING* this interface is highly subject to change
4097 *
4098 * Returns 0 if everything goes fine, a positive error code
4099 * if something is not valid and -1 if an internal error occurs.
4100 */
4101static int
4102xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4103 xmlSchemaPtr schema,
4104 xmlSchemaWildcardPtr wildc,
4105 xmlNodePtr node)
4106{
4107 const xmlChar *pc, *ns, *dictnsItem;
4108 int ret = 0;
4109 xmlChar *nsItem;
4110 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4111 xmlAttrPtr attr;
4112
4113 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4114 if ((pc == NULL)
4115 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4116 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4117 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4118 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4119 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4120 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4121 } else {
4122 xmlSchemaPSimpleTypeErr(ctxt,
4123 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4124 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004125 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004126 NULL, NULL, NULL);
4127 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4128 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4129 }
4130 /*
4131 * Build the namespace constraints.
4132 */
4133 attr = xmlSchemaGetPropNode(node, "namespace");
4134 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4135 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4136 wildc->any = 1;
4137 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4138 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4139 if (wildc->negNsSet == NULL) {
4140 return (-1);
4141 }
4142 wildc->negNsSet->value = schema->targetNamespace;
4143 } else {
4144 const xmlChar *end, *cur;
4145
4146 cur = ns;
4147 do {
4148 while (IS_BLANK_CH(*cur))
4149 cur++;
4150 end = cur;
4151 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4152 end++;
4153 if (end == cur)
4154 break;
4155 nsItem = xmlStrndup(cur, end - cur);
4156 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4157 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4158 xmlSchemaPSimpleTypeErr(ctxt,
4159 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4160 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004161 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004162 "((##any | ##other) | List of (anyURI | "
4163 "(##targetNamespace | ##local)))",
4164 nsItem, NULL, NULL, NULL);
4165 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4166 } else {
4167 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4168 dictnsItem = schema->targetNamespace;
4169 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4170 dictnsItem = NULL;
4171 } else {
4172 /*
4173 * Validate the item (anyURI).
4174 */
4175 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4176 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4177 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4178 }
4179 /*
4180 * Avoid dublicate namespaces.
4181 */
4182 tmp = wildc->nsSet;
4183 while (tmp != NULL) {
4184 if (dictnsItem == tmp->value)
4185 break;
4186 tmp = tmp->next;
4187 }
4188 if (tmp == NULL) {
4189 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4190 if (tmp == NULL) {
4191 xmlFree(nsItem);
4192 return (-1);
4193 }
4194 tmp->value = dictnsItem;
4195 tmp->next = NULL;
4196 if (wildc->nsSet == NULL)
4197 wildc->nsSet = tmp;
4198 else
4199 lastNs->next = tmp;
4200 lastNs = tmp;
4201 }
4202
4203 }
4204 xmlFree(nsItem);
4205 cur = end;
4206 } while (*cur != 0);
4207 }
4208 return (ret);
4209}
4210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004211 * xmlSchemaParseAny:
4212 * @ctxt: a schema validation context
4213 * @schema: the schema being built
4214 * @node: a subtree containing XML Schema informations
4215 *
4216 * parse a XML schema Any declaration
4217 * *WARNING* this interface is highly subject to change
4218 *
4219 * Returns the new type structure or NULL in case of error
4220 */
4221static xmlSchemaTypePtr
4222xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4223 xmlNodePtr node)
4224{
4225 xmlSchemaTypePtr type;
4226 xmlNodePtr child = NULL;
4227 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004228 xmlSchemaWildcardPtr wildc;
Daniel Veillard4255d502002-04-16 15:50:10 +00004229
4230 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4231 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004232 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004233 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004234 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 type->node = node;
4237 type->type = XML_SCHEMA_TYPE_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4239 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004240 wildc = xmlSchemaAddWildcard(ctxt);
4241 /*
4242 * This is not nice, since it is won't be used as a attribute wildcard,
4243 * but better than adding a field to the structure.
4244 */
4245 type->attributeWildcard = wildc;
4246 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
4247 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004249 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4250 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 }
4252 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 xmlSchemaPErr2(ctxt, node, child,
4254 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4255 "Sequence %s has unexpected content\n", type->name,
4256 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004257 }
4258
4259 return (type);
4260}
4261
4262/**
4263 * xmlSchemaParseNotation:
4264 * @ctxt: a schema validation context
4265 * @schema: the schema being built
4266 * @node: a subtree containing XML Schema informations
4267 *
4268 * parse a XML schema Notation declaration
4269 *
4270 * Returns the new structure or NULL in case of error
4271 */
4272static xmlSchemaNotationPtr
4273xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004274 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004275{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004276 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 xmlSchemaNotationPtr ret;
4278 xmlNodePtr child = NULL;
4279
4280 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4281 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004282 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004283 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004284 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4285 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004286 return (NULL);
4287 }
4288 ret = xmlSchemaAddNotation(ctxt, schema, name);
4289 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 return (NULL);
4291 }
4292 child = node->children;
4293 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4295 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004296 }
4297 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298 xmlSchemaPErr2(ctxt, node, child,
4299 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4300 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004301 }
4302
4303 return (ret);
4304}
4305
4306/**
4307 * xmlSchemaParseAnyAttribute:
4308 * @ctxt: a schema validation context
4309 * @schema: the schema being built
4310 * @node: a subtree containing XML Schema informations
4311 *
4312 * parse a XML schema AnyAttrribute declaration
4313 * *WARNING* this interface is highly subject to change
4314 *
4315 * Returns an attribute def structure or NULL
4316 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004317static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4319 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004320{
Daniel Veillard3646d642004-06-02 19:19:14 +00004321 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004322 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004323
4324 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4325 return (NULL);
4326
Daniel Veillard3646d642004-06-02 19:19:14 +00004327 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 if (ret == NULL) {
4329 return (NULL);
4330 }
William M. Bracke7091952004-05-11 15:09:58 +00004331 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004332 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004333 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4334 xmlSchemaFreeWildcard(ret);
4335 return (NULL);
4336 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004337 child = node->children;
4338 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004339 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4340 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004341 }
4342 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004343 /* TODO: Change the error code. */
4344 xmlSchemaPContentErr(ctxt,
4345 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
4346 NULL, NULL, node, child,
4347 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 }
4349
4350 return (ret);
4351}
4352
4353
4354/**
4355 * xmlSchemaParseAttribute:
4356 * @ctxt: a schema validation context
4357 * @schema: the schema being built
4358 * @node: a subtree containing XML Schema informations
4359 *
4360 * parse a XML schema Attrribute declaration
4361 * *WARNING* this interface is highly subject to change
4362 *
William M. Bracke7091952004-05-11 15:09:58 +00004363 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 */
4365static xmlSchemaAttributePtr
4366xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004367 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004368{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004369 const xmlChar *name, *attrValue;
4370 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004372 xmlNodePtr child = NULL;
4373 xmlAttrPtr attr, nameAttr;
4374 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004375
4376 /*
4377 * Note that the w3c spec assumes the schema to be validated with schema
4378 * for schemas beforehand.
4379 *
4380 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004381 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004382
4383 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4384 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004385 attr = xmlSchemaGetPropNode(node, "ref");
4386 nameAttr = xmlSchemaGetPropNode(node, "name");
4387
4388 if ((attr == NULL) && (nameAttr == NULL)) {
4389 /*
4390 * 3.2.3 : 3.1
4391 * One of ref or name must be present, but not both
4392 */
4393 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4394 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4395 "One of the attributes 'ref' or 'name' must be present");
4396 return (NULL);
4397 }
4398 if ((topLevel) || (attr == NULL)) {
4399 if (nameAttr == NULL) {
4400 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4401 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4402 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004403 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004404 }
4405 } else
4406 isRef = 1;
4407
4408 if (isRef) {
4409 char buf[100];
4410 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4411
4412 /*
4413 * Parse as attribute reference.
4414 */
4415 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4416 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4417 &refPrefix, &ref) != 0) {
4418 return (NULL);
4419 }
4420 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4421 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004422 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004423 if (ret == NULL) {
4424 if (repName != NULL)
4425 xmlFree(repName);
4426 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004427 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004428 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4429 ret->node = node;
4430 ret->refNs = refNs;
4431 ret->refPrefix = refPrefix;
4432 ret->ref = ref;
4433 /*
4434 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4435 */
4436 if (nameAttr != NULL)
4437 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4438 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4439 "ref", "name");
4440 /*
4441 * Check for illegal attributes.
4442 */
4443 attr = node->properties;
4444 while (attr != NULL) {
4445 if (attr->ns == NULL) {
4446 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4447 xmlStrEqual(attr->name, BAD_CAST "form")) {
4448 /*
4449 * 3.2.3 : 3.2
4450 * If ref is present, then all of <simpleType>,
4451 * form and type must be absent.
4452 */
4453 xmlSchemaPIllegalAttrErr(ctxt,
4454 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4455 (xmlSchemaTypePtr) ret, attr);
4456 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4457 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4458 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4459 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4460 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4461 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4462 xmlSchemaPIllegalAttrErr(ctxt,
4463 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4464 &repName, (xmlSchemaTypePtr) ret, attr);
4465 }
4466 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4467 xmlSchemaPIllegalAttrErr(ctxt,
4468 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4469 &repName, (xmlSchemaTypePtr) ret, attr);
4470 }
4471 attr = attr->next;
4472 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004473 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004474 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004475
4476 /*
4477 * Parse as attribute declaration.
4478 */
4479 if (xmlSchemaPValAttrNode(ctxt,
4480 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4481 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4482 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004483 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004484 /*
4485 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4486 */
4487 /*
4488 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4489 */
4490 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4491 xmlSchemaPSimpleTypeErr(ctxt,
4492 XML_SCHEMAP_NO_XMLNS,
4493 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004495 "The value must not match 'xmlns'",
4496 NULL, NULL);
4497 if (repName != NULL)
4498 xmlFree(repName);
4499 return (NULL);
4500 }
4501 /*
4502 * Evaluate the target namespace
4503 */
William M. Bracke7091952004-05-11 15:09:58 +00004504 if (schema->targetNamespace != NULL) {
4505 if (topLevel) {
4506 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004507 } else {
4508 attr = xmlSchemaGetPropNode(node, "form");
4509 if (attr != NULL) {
4510 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4511 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4512 ns = schema->targetNamespace;
4513 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4514 xmlSchemaPSimpleTypeErr(ctxt,
4515 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4516 &repName, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004517 NULL, "(qualified | unqualified)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004518 attrValue, NULL, NULL, NULL);
4519 }
4520 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4521 ns = schema->targetNamespace;
4522 }
4523 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004524 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004525 if (ret == NULL) {
4526 if (repName != NULL)
4527 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004528 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004529 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004530 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4531 ret->node = node;
4532 if (topLevel)
4533 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4534 /*
4535 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4536 */
4537 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4538 xmlSchemaPCustomErr(ctxt,
4539 XML_SCHEMAP_NO_XSI,
4540 &repName, (xmlSchemaTypePtr) ret, node,
4541 "The target namespace must not match '%s'",
4542 xmlSchemaInstanceNs);
4543 }
4544 /*
4545 * Check for illegal attributes.
4546 */
4547 attr = node->properties;
4548 while (attr != NULL) {
4549 if (attr->ns == NULL) {
4550 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4551 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4552 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4553 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4554 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4555 if ((topLevel) ||
4556 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4557 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4558 xmlSchemaPIllegalAttrErr(ctxt,
4559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4560 &repName, (xmlSchemaTypePtr) ret, attr);
4561 }
4562 }
4563 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4564 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4565 &repName, (xmlSchemaTypePtr) ret, attr);
4566 }
4567 attr = attr->next;
4568 }
4569 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4570 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004571 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004572 /* TODO: Check ID. */
4573 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004574 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004575 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004576 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004577 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4578 if (ret->defValue != NULL)
4579 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4580 /*
4581 * Attribute "default".
4582 */
4583 attr = xmlSchemaGetPropNode(node, "default");
4584 if (attr != NULL) {
4585 /*
4586 * 3.2.3 : 1
4587 * default and fixed must not both be present.
4588 */
4589 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4590 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4591 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4592 } else
4593 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4594 }
4595 if (topLevel == 0) {
4596 /*
4597 * Attribute "use".
4598 */
4599 attr = xmlSchemaGetPropNode(node, "use");
4600 if (attr != NULL) {
4601 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4602 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4603 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4604 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4605 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4606 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4607 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4608 else
4609 xmlSchemaPSimpleTypeErr(ctxt,
4610 XML_SCHEMAP_INVALID_ATTR_USE,
4611 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004612 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004613 attrValue, NULL, NULL, NULL);
4614 } else
4615 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4616 /*
4617 * 3.2.3 : 2
4618 * If default and use are both present, use must have
4619 * the actual value optional.
4620 */
4621 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4622 (ret->defValue != NULL) &&
4623 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4624 xmlSchemaPSimpleTypeErr(ctxt,
4625 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4626 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004627 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004628 "The value must be 'optional' if the attribute "
4629 "'default' is present as well", NULL, NULL);
4630 }
4631 }
4632 /*
4633 * And now for the children...
4634 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004635 child = node->children;
4636 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4638 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004639 }
4640 if (isRef) {
4641 if (child != NULL) {
4642 if (IS_SCHEMA(child, "simpleType"))
4643 /*
4644 * 3.2.3 : 3.2
4645 * If ref is present, then all of <simpleType>,
4646 * form and type must be absent.
4647 */
4648 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4649 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4650 "(annotation?)");
4651 else
4652 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4653 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4654 "(annotation?)");
4655 }
4656 } else {
4657 if (IS_SCHEMA(child, "simpleType")) {
4658 if (ret->typeName != NULL) {
4659 /*
4660 * 3.2.3 : 4
4661 * type and <simpleType> must not both be present.
4662 */
4663 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4664 &repName, (xmlSchemaTypePtr) ret, node, child,
4665 "The attribute 'type' and the <simpleType> child "
4666 "are mutually exclusive", NULL);
4667 } else
4668 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4669 child = child->next;
4670 }
4671 if (child != NULL)
4672 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4673 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4674 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004675 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004676 /*
4677 * Cleanup.
4678 */
4679 if (repName != NULL)
4680 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004681 return (ret);
4682}
4683
4684/**
4685 * xmlSchemaParseAttributeGroup:
4686 * @ctxt: a schema validation context
4687 * @schema: the schema being built
4688 * @node: a subtree containing XML Schema informations
4689 *
4690 * parse a XML schema Attribute Group declaration
4691 * *WARNING* this interface is highly subject to change
4692 *
4693 * Returns the attribute group or NULL in case of error.
4694 */
4695static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004696xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004697 xmlSchemaPtr schema, xmlNodePtr node,
4698 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004699{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004700 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004701 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004702 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004703 const xmlChar *oldcontainer;
4704 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004705
4706 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4707 return (NULL);
4708 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004709 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004710 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004711 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
4712 if (ref == NULL) {
4713 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004714 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
4715 "Attribute group or particle: One of the attributes 'name' "
4716 "or 'ref' must be present.\n", NULL,
4717 NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004718 return (NULL);
4719 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004720 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
4721 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004722 if (name == NULL) {
4723 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
4724 return (NULL);
4725 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004726 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004727 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004728 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004729 return (NULL);
4730 }
4731 ret->ref = ref;
4732 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004733 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00004734 if (topLevel)
4735 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004736 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00004737 child = node->children;
4738 ctxt->container = name;
4739 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004740 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4741 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004742 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004743 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004744 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004745 xmlSchemaPErr2(ctxt, node, child,
4746 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004747 "Attribute group '%s' has unexpected content.\n", name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004748 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004749 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004750 ctxt->container = oldcontainer;
4751 return (ret);
4752}
4753
4754/**
William M. Brack2f2a6632004-08-20 23:09:47 +00004755 * xmlSchemaPValAttrFormDefault:
4756 * @value: the value
4757 * @flags: the flags to be modified
4758 * @flagQualified: the specific flag for "qualified"
4759 *
4760 * Returns 0 if the value is valid, 1 otherwise.
4761 */
4762static int
4763xmlSchemaPValAttrFormDefault(const xmlChar *value,
4764 int *flags,
4765 int flagQualified)
4766{
4767 if (xmlStrEqual(value, BAD_CAST "qualified")) {
4768 if ((*flags & flagQualified) == 0)
4769 *flags |= flagQualified;
4770 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
4771 return (1);
4772
4773 return (0);
4774}
4775
4776/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004777 * xmlSchemaPValAttrBlockFinal:
4778 * @value: the value
4779 * @flags: the flags to be modified
4780 * @flagAll: the specific flag for "#all"
4781 * @flagExtension: the specific flag for "extension"
4782 * @flagRestriction: the specific flag for "restriction"
4783 * @flagSubstitution: the specific flag for "substitution"
4784 * @flagList: the specific flag for "list"
4785 * @flagUnion: the specific flag for "union"
4786 *
4787 * Validates the value of the attribute "final" and "block". The value
4788 * is converted into the specified flag values and returned in @flags.
4789 *
4790 * Returns 0 if the value is valid, 1 otherwise.
4791 */
4792
4793static int
4794xmlSchemaPValAttrBlockFinal(const xmlChar *value,
4795 int *flags,
4796 int flagAll,
4797 int flagExtension,
4798 int flagRestriction,
4799 int flagSubstitution,
4800 int flagList,
4801 int flagUnion)
4802{
4803 int ret = 0;
4804
4805 /*
4806 * TODO: This does not check for dublicate entries.
4807 */
William M. Brack2f2a6632004-08-20 23:09:47 +00004808 if (value == NULL)
4809 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810 if (xmlStrEqual(value, BAD_CAST "#all")) {
4811 if (flagAll != -1)
4812 *flags |= flagAll;
4813 else {
4814 if (flagExtension != -1)
4815 *flags |= flagExtension;
4816 if (flagRestriction != -1)
4817 *flags |= flagRestriction;
4818 if (flagSubstitution != -1)
4819 *flags |= flagSubstitution;
4820 if (flagList != -1)
4821 *flags |= flagList;
4822 if (flagUnion != -1)
4823 *flags |= flagUnion;
4824 }
4825 } else {
4826 const xmlChar *end, *cur = value;
4827 xmlChar *item;
4828
4829 do {
4830 while (IS_BLANK_CH(*cur))
4831 cur++;
4832 end = cur;
4833 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4834 end++;
4835 if (end == cur)
4836 break;
4837 item = xmlStrndup(cur, end - cur);
4838 if (xmlStrEqual(item, BAD_CAST "extension")) {
4839 if (flagExtension != -1) {
4840 if ((*flags & flagExtension) == 0)
4841 *flags |= flagExtension;
4842 } else
4843 ret = 1;
4844 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4845 if (flagRestriction != -1) {
4846 if ((*flags & flagRestriction) == 0)
4847 *flags |= flagRestriction;
4848 } else
4849 ret = 1;
4850 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
4851 if (flagSubstitution != -1) {
4852 if ((*flags & flagSubstitution) == 0)
4853 *flags |= flagSubstitution;
4854 } else
4855 ret = 1;
4856 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4857 if (flagList != -1) {
4858 if ((*flags & flagList) == 0)
4859 *flags |= flagList;
4860 } else
4861 ret = 1;
4862 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4863 if (flagUnion != -1) {
4864 if ((*flags & flagUnion) == 0)
4865 *flags |= flagUnion;
4866 } else
4867 ret = 1;
4868 } else
4869 ret = 1;
4870 if (item != NULL)
4871 xmlFree(item);
4872 cur = end;
4873 } while ((ret == 0) && (*cur != 0));
4874 }
4875
4876 return (ret);
4877}
4878
4879/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004880 * xmlSchemaParseElement:
4881 * @ctxt: a schema validation context
4882 * @schema: the schema being built
4883 * @node: a subtree containing XML Schema informations
4884 *
4885 * parse a XML schema Element declaration
4886 * *WARNING* this interface is highly subject to change
4887 *
William M. Bracke7091952004-05-11 15:09:58 +00004888 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004889 */
4890static xmlSchemaElementPtr
4891xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004892 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004893{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004894 const xmlChar *name = NULL;
4895 const xmlChar *attrValue;
4896 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004897 xmlSchemaElementPtr ret;
4898 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004899 const xmlChar *oldcontainer;
4900 xmlAttrPtr attr, nameAttr;
4901 int minOccurs, maxOccurs;
4902 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004903
4904 /* 3.3.3 Constraints on XML Representations of Element Declarations */
4905 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004906
Daniel Veillard4255d502002-04-16 15:50:10 +00004907 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4908 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004909
Daniel Veillardc0826a72004-08-10 14:17:33 +00004910 oldcontainer = ctxt->container;
4911
4912 nameAttr = xmlSchemaGetPropNode(node, "name");
4913 attr = xmlSchemaGetPropNode(node, "ref");
4914 if ((topLevel) || (attr == NULL)) {
4915 if (nameAttr == NULL) {
4916 xmlSchemaPMissingAttrErr(ctxt,
4917 XML_SCHEMAP_S4S_ATTR_MISSING,
4918 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
4919 "name", NULL);
4920 return (NULL);
4921 }
4922 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
4923 } else {
4924 isRef = 1;
4925
4926 }
4927 /*
4928 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
4929 * to no component at all
4930 * TODO: It might be better to validate the element, even if it won't be
4931 * used.
4932 */
4933 minOccurs = xmlGetMinOccurs(ctxt, node);
4934 maxOccurs = xmlGetMaxOccurs(ctxt, node);
4935 if ((minOccurs == 0) && (maxOccurs == 0))
4936 return (NULL);
4937 /*
4938 * If we get a "ref" attribute on a local <element> we will assume it's
4939 * a reference - even if there's a "name" attribute; this seems to be more
4940 * robust.
4941 */
4942 if (isRef) {
4943 char buf[100];
4944 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
4945
4946 /*
4947 * Parse as a particle.
4948 */
4949 xmlSchemaPValAttrNodeQName(ctxt, schema,
4950 (xmlChar **) &xmlSchemaElemDesAttrRef,
4951 NULL, attr, &refNs, &refPrefix, &ref);
4952
4953 snprintf(buf, 99, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004954 name = (const xmlChar *) buf;
4955 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004956 if (ret == NULL) {
4957 if (repName != NULL)
4958 xmlFree(repName);
4959 return (NULL);
4960 }
4961 ret->type = XML_SCHEMA_TYPE_ELEMENT;
4962 ret->node = node;
4963 ret->ref = ref;
4964 ret->refNs = refNs;
4965 ret->refPrefix = refPrefix;
4966 ret->flags |= XML_SCHEMAS_ELEM_REF;
4967 /*
4968 * Check for illegal attributes.
4969 */
4970 /*
4971 * 3.3.3 : 2.1
4972 * One of ref or name must be present, but not both
4973 */
4974 if (nameAttr != NULL) {
4975 xmlSchemaPMutualExclAttrErr(ctxt,
4976 XML_SCHEMAP_SRC_ELEMENT_2_1,
4977 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4978 "ref", "name");
4979 }
4980 /* 3.3.3 : 2.2 */
4981 attr = node->properties;
4982 while (attr != NULL) {
4983 if (attr->ns == NULL) {
4984 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4985 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4986 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
4987 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
4988 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
4989 xmlSchemaPCustomAttrErr(ctxt,
4990 XML_SCHEMAP_SRC_ELEMENT_2_2,
4991 &repName, (xmlSchemaTypePtr) ret, attr,
4992 "Only the attributes 'minOccurs', 'maxOccurs' and "
4993 "'id' are allowed in addition to 'ref'");
4994 break;
4995 }
4996 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4997 xmlSchemaPIllegalAttrErr(ctxt,
4998 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4999 &repName, (xmlSchemaTypePtr) ret, attr);
5000 }
5001 attr = attr->next;
5002 }
5003 } else {
5004 const xmlChar *ns = NULL, *fixed;
5005
5006 /*
5007 * Parse as an element declaration.
5008 */
5009 if (xmlSchemaPValAttrNode(ctxt,
5010 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5011 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5012 return (NULL);
5013 /*
5014 * Evaluate the target namespace.
5015 */
William M. Bracke7091952004-05-11 15:09:58 +00005016 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005017 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00005018 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 } else {
5020 attr = xmlSchemaGetPropNode(node, "form");
5021 if (attr != NULL) {
5022 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5023 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5024 ns = schema->targetNamespace;
5025 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5026 xmlSchemaPSimpleTypeErr(ctxt,
5027 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5028 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL,
5029 (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005030 NULL, "(qualified | unqualified)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005031 attrValue, NULL, NULL, NULL);
5032 }
5033 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
William M. Bracke7091952004-05-11 15:09:58 +00005034 ns = schema->targetNamespace;
William M. Bracke7091952004-05-11 15:09:58 +00005035 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005036 }
5037 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 if (ret == NULL) {
5039 if (repName != NULL)
5040 xmlFree(repName);
5041 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005042 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005043 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5044 ret->node = node;
5045 /*
5046 * Check for illegal attributes.
5047 */
William M. Bracke7091952004-05-11 15:09:58 +00005048 attr = node->properties;
5049 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005050 if (attr->ns == NULL) {
5051 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5052 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5053 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5054 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5055 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5056 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
5057 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
5058 if (topLevel == 0) {
5059 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5060 /*
5061 * 3.3.6 : 3 If there is a non-·absent· {substitution
5062 * group affiliation}, then {scope} must be global.
5063 * TODO: This one is redundant, since the S4S does
5064 * prohibit this attribute on local declarations already;
5065 * so why an explicit error code? Weird spec.
William M. Brack2f2a6632004-08-20 23:09:47 +00005066 * TODO: Move this to the proper constraint layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 */
5068 xmlSchemaPIllegalAttrErr(ctxt,
5069 XML_SCHEMAP_E_PROPS_CORRECT_3,
5070 &repName, (xmlSchemaTypePtr) ret, attr);
5071 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5072 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5073 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005074
Daniel Veillardc0826a72004-08-10 14:17:33 +00005075 xmlSchemaPIllegalAttrErr(ctxt,
5076 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5077 &repName, (xmlSchemaTypePtr) ret, attr);
5078 }
5079 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5080 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5081 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5082
5083 xmlSchemaPIllegalAttrErr(ctxt,
5084 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5085 &repName, (xmlSchemaTypePtr) ret, attr);
5086 }
5087 }
5088 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5089
5090 xmlSchemaPIllegalAttrErr(ctxt,
5091 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5092 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005093 }
5094 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005095 }
William M. Bracke7091952004-05-11 15:09:58 +00005096 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005097 * Extract/validate attributes.
5098 */
5099 if (topLevel) {
5100 /*
5101 * Process top attributes of global element declarations here.
5102 */
5103 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5104 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5105 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5106 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5107 &(ret->substGroupNs), NULL, &(ret->substGroup));
5108 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5109 node, "abstract", 0))
5110 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5111 /*
5112 * Attribute "final".
5113 */
5114 attr = xmlSchemaGetPropNode(node, "final");
5115 if (attr == NULL) {
5116 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5117 } else {
5118 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5119 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5120 -1,
5121 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5122 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5123 xmlSchemaPSimpleTypeErr(ctxt,
5124 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5125 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005126 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005127 attrValue, NULL, NULL, NULL);
5128 }
5129 }
5130 }
5131 /*
5132 * Attribute "block".
5133 */
5134 attr = xmlSchemaGetPropNode(node, "block");
5135 if (attr == NULL) {
5136 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5137 } else {
5138 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5139 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5140 -1,
5141 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5142 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5143 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5144 xmlSchemaPSimpleTypeErr(ctxt,
5145 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5146 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005147 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005148 "restriction | substitution))", attrValue,
5149 NULL, NULL, NULL);
5150 }
5151 }
5152 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5153 node, "nillable", 0))
5154 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005155
Daniel Veillardc0826a72004-08-10 14:17:33 +00005156 xmlSchemaPValAttrQName(ctxt, schema,
5157 &repName, (xmlSchemaTypePtr) ret, node,
5158 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005159
Daniel Veillardc0826a72004-08-10 14:17:33 +00005160 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5161 attr = xmlSchemaGetPropNode(node, "fixed");
5162 if (attr != NULL) {
5163 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5164 if (ret->value != NULL) {
5165 /*
5166 * 3.3.3 : 1
5167 * default and fixed must not both be present.
5168 */
5169 xmlSchemaPMutualExclAttrErr(ctxt,
5170 XML_SCHEMAP_SRC_ELEMENT_1,
5171 &repName, (xmlSchemaTypePtr) ret, attr,
5172 "default", "fixed");
5173 } else {
5174 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5175 ret->value = fixed;
5176 }
5177 }
5178 }
5179 /*
5180 * Extract/validate common attributes.
5181 */
5182 /* TODO: Check ID: */
5183 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5184 ret->minOccurs = minOccurs;
5185 ret->maxOccurs = maxOccurs;
5186 if ((topLevel != 1) && (ret->maxOccurs != UNBOUNDED)) {
5187 /*
5188 * TODO: Maby we should better not create the element/particle,
5189 * if min/max is invalid, since it could confuse the build of the
5190 * content model.
5191 */
5192 /*
5193 * 3.9.6 Schema Component Constraint: Particle Correct
5194 *
5195 */
5196 if (maxOccurs < 1) {
5197 /*
5198 * 2.2 {max occurs} must be greater than or equal to 1.
5199 */
5200 xmlSchemaPCustomAttrErr(ctxt,
5201 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5202 &repName, (xmlSchemaTypePtr) ret,
5203 xmlSchemaGetPropNode(node, "maxOccurs"),
5204 "The value must be greater than or equal to 1");
5205 } else if (minOccurs > maxOccurs) {
5206 /*
5207 * 2.1 {min occurs} must not be greater than {max occurs}.
5208 */
5209 xmlSchemaPCustomAttrErr(ctxt,
5210 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5211 &repName, (xmlSchemaTypePtr) ret,
5212 xmlSchemaGetPropNode(node, "minOccurs"),
5213 "The value must not be greater than the value of 'maxOccurs'");
5214 }
5215 }
5216
5217 /*
5218 * And now for the children...
5219 */
5220 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 child = node->children;
5222 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005223 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005225 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005226 if (isRef) {
5227 if (child != NULL) {
5228 xmlSchemaPContentErr(ctxt,
5229 XML_SCHEMAP_SRC_ELEMENT_2_2,
5230 &repName, (xmlSchemaTypePtr) ret, node, child,
5231 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005232 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005233 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005234 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005235 /*
5236 * 3.3.3 : 3
5237 * "type" and either <simpleType> or <complexType> are mutually
5238 * exclusive
5239 */
William M. Bracke7091952004-05-11 15:09:58 +00005240 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005241 xmlSchemaPContentErr(ctxt,
5242 XML_SCHEMAP_SRC_ELEMENT_3,
5243 &repName, (xmlSchemaTypePtr) ret, node, child,
5244 "The attribute 'type' and the <complexType> child are "
5245 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005246 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005247 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005248 child = child->next;
5249 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005250 /*
5251 * 3.3.3 : 3
5252 * "type" and either <simpleType> or <complexType> are
5253 * mutually exclusive
5254 */
William M. Bracke7091952004-05-11 15:09:58 +00005255 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005256 xmlSchemaPContentErr(ctxt,
5257 XML_SCHEMAP_SRC_ELEMENT_3,
5258 &repName, (xmlSchemaTypePtr) ret, node, child,
5259 "The attribute 'type' and the <simpleType> child are "
5260 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005261 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005262 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005263 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005264 }
William M. Bracke7091952004-05-11 15:09:58 +00005265 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005266 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005267 TODO child = child->next;
5268 }
5269 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005270 xmlSchemaPContentErr(ctxt,
5271 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5272 &repName, (xmlSchemaTypePtr) ret, node, child,
5273 NULL, "(annotation?, ((simpleType | complexType)?, "
5274 "(unique | key | keyref)*))");
5275 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005276
Daniel Veillardc0826a72004-08-10 14:17:33 +00005277 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005278 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005279 /*
5280 * Cleanup.
5281 */
5282 if (repName != NULL)
5283 xmlFree(repName);
5284 /*
5285 * NOTE: Element Declaration Representation OK 4. will be checked at a
5286 * different layer.
5287 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 return (ret);
5289}
5290
5291/**
5292 * xmlSchemaParseUnion:
5293 * @ctxt: a schema validation context
5294 * @schema: the schema being built
5295 * @node: a subtree containing XML Schema informations
5296 *
5297 * parse a XML schema Union definition
5298 * *WARNING* this interface is highly subject to change
5299 *
William M. Bracke7091952004-05-11 15:09:58 +00005300 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005301 * 1 in case of success.
5302 */
5303static xmlSchemaTypePtr
5304xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005305 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005306{
5307 xmlSchemaTypePtr type, subtype, last = NULL;
5308 xmlNodePtr child = NULL;
5309 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005310 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005311
5312 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5313 return (NULL);
5314
William M. Brack2f2a6632004-08-20 23:09:47 +00005315 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5316 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 if (type == NULL)
5318 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005319 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005320 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005321 /*
5322 * Check for illegal attributes.
5323 */
5324 attr = node->properties;
5325 while (attr != NULL) {
5326 if (attr->ns == NULL) {
5327 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5328 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5329 xmlSchemaPIllegalAttrErr(ctxt,
5330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5331 NULL, type, attr);
5332 }
5333 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5334 xmlSchemaPIllegalAttrErr(ctxt,
5335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5336 NULL, type, attr);
5337 }
5338 attr = attr->next;
5339 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005340 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005341 /*
5342 * Attribute "memberTypes". This is a list of QNames.
5343 * TODO: Validate the QNames.
5344 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005345 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005346 /*
5347 * And now for the children...
5348 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 child = node->children;
5350 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005351 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5352 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005353 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005354 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005355 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005356 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005357 if (subtype != NULL) {
5358 if (last == NULL) {
5359 type->subtypes = subtype;
5360 last = subtype;
5361 } else {
5362 last->next = subtype;
5363 last = subtype;
5364 }
5365 last->next = NULL;
5366 }
5367 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005368 }
5369 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005370 /* TODO: Think about the error code. */
5371 xmlSchemaPContentErr(ctxt,
5372 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5373 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005374 }
5375 return (type);
5376}
5377
5378/**
5379 * xmlSchemaParseList:
5380 * @ctxt: a schema validation context
5381 * @schema: the schema being built
5382 * @node: a subtree containing XML Schema informations
5383 *
5384 * parse a XML schema List definition
5385 * *WARNING* this interface is highly subject to change
5386 *
William M. Bracke7091952004-05-11 15:09:58 +00005387 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 * 1 in case of success.
5389 */
5390static xmlSchemaTypePtr
5391xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005392 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005393{
5394 xmlSchemaTypePtr type, subtype;
5395 xmlNodePtr child = NULL;
5396 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005397 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005398
5399 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5400 return (NULL);
5401
William M. Brack2f2a6632004-08-20 23:09:47 +00005402 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5403 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005404 if (type == NULL)
5405 return (NULL);
5406 type->node = node;
5407 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005408 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005409 /*
5410 * Check for illegal attributes.
5411 */
5412 attr = node->properties;
5413 while (attr != NULL) {
5414 if (attr->ns == NULL) {
5415 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5417 xmlSchemaPIllegalAttrErr(ctxt,
5418 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5419 NULL, type, attr);
5420 }
5421 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5422 xmlSchemaPIllegalAttrErr(ctxt,
5423 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5424 NULL, type, attr);
5425 }
5426 attr = attr->next;
5427 }
5428 /*
5429 * Attribute "itemType".
5430 */
5431 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5432 node, "itemType", &(type->baseNs), NULL, &(type->base));
5433 /*
5434 * And now for the children...
5435 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005436 child = node->children;
5437 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005438 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5439 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005440 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005441 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005442 if (IS_SCHEMA(child, "simpleType")) {
5443 if (type->base != NULL) {
5444 xmlSchemaPCustomErr(ctxt,
5445 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5446 NULL, type, node,
5447 "The attribute 'itemType' and the <simpleType> child "
5448 "are mutually exclusive", NULL);
5449 } else {
5450 subtype = (xmlSchemaTypePtr)
5451 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5452 type->subtypes = subtype;
5453 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005454 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005455 }
5456 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005457 /* TODO: Think about the error code. */
5458 xmlSchemaPContentErr(ctxt,
5459 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5460 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005461 }
5462 return (type);
5463}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005464
Daniel Veillard4255d502002-04-16 15:50:10 +00005465/**
5466 * xmlSchemaParseSimpleType:
5467 * @ctxt: a schema validation context
5468 * @schema: the schema being built
5469 * @node: a subtree containing XML Schema informations
5470 *
5471 * parse a XML schema Simple Type definition
5472 * *WARNING* this interface is highly subject to change
5473 *
William M. Bracke7091952004-05-11 15:09:58 +00005474 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005475 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005476 */
5477static xmlSchemaTypePtr
5478xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005479 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005480{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005481 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005482 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005483 const xmlChar *attrValue = NULL;
5484 xmlChar *repName = NULL;
5485 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005486
5487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5488 return (NULL);
5489
Daniel Veillardc0826a72004-08-10 14:17:33 +00005490 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005491
Daniel Veillardc0826a72004-08-10 14:17:33 +00005492 if (topLevel) {
5493 if (attr == NULL) {
5494 xmlSchemaPMissingAttrErr(ctxt,
5495 XML_SCHEMAP_S4S_ATTR_MISSING,
5496 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5497 "name", NULL);
5498 return (NULL);
5499 } else if (xmlSchemaPValAttrNode(ctxt,
5500 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5501 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005502 return (NULL);
5503 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005504 }
5505
5506 if (topLevel == 0) {
5507 char buf[100];
5508
Daniel Veillard01fa6152004-06-29 17:04:39 +00005509 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005510 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005511 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005512 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005513 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005514 if (type == NULL)
5515 return (NULL);
5516 type->node = node;
5517 type->type = XML_SCHEMA_TYPE_SIMPLE;
5518 /*
5519 * Check for illegal attributes.
5520 */
5521 attr = node->properties;
5522 while (attr != NULL) {
5523 if (attr->ns == NULL) {
5524 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5525 xmlSchemaPIllegalAttrErr(ctxt,
5526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5527 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005529 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5530 xmlSchemaPIllegalAttrErr(ctxt,
5531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5532 &repName, type, attr);
5533 }
5534 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005535 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 } else {
5537 /*
5538 * Parse as global simple type definition.
5539 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005540 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005541 if (type == NULL)
5542 return (NULL);
5543 type->node = node;
5544 type->type = XML_SCHEMA_TYPE_SIMPLE;
5545 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5546 /*
5547 * Check for illegal attributes.
5548 */
5549 attr = node->properties;
5550 while (attr != NULL) {
5551 if (attr->ns == NULL) {
5552 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5553 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5554 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5555 xmlSchemaPIllegalAttrErr(ctxt,
5556 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5557 &repName, type, attr);
5558 }
5559 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5560 xmlSchemaPIllegalAttrErr(ctxt,
5561 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5562 &repName, type, attr);
5563 }
5564 attr = attr->next;
5565 }
5566 /*
5567 * Attribute "final".
5568 */
5569 attr = xmlSchemaGetPropNode(node, "final");
5570 if (attr == NULL) {
5571 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5572 } else {
5573 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5574 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5575 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5576 XML_SCHEMAS_TYPE_FINAL_LIST,
5577 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5578
5579 xmlSchemaPSimpleTypeErr(ctxt,
5580 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5581 &repName, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005582 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 attrValue, NULL, NULL, NULL);
5584 }
5585 }
5586 }
5587 /* TODO: Check id. */
5588 type->id = xmlSchemaGetProp(ctxt, node, "id");
5589 /*
5590 * And now for the children...
5591 */
5592 ctxtType = ctxt->ctxtType;
5593 ctxt->ctxtType = type;
5594 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005595 child = node->children;
5596 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005597 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5598 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005599 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005600 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005601 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005602 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005603 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005604 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005605 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606 subtype = (xmlSchemaTypePtr)
5607 xmlSchemaParseList(ctxt, schema, child);
5608 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005610 subtype = (xmlSchemaTypePtr)
5611 xmlSchemaParseUnion(ctxt, schema, child);
5612 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005613 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 type->subtypes = subtype;
5615 if ((child != NULL) || (subtype == NULL)) {
5616 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5617 &repName, type, node, child, NULL,
5618 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005619 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005620 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005621 if (repName != NULL)
5622 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005623
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 return (type);
5625}
5626
5627
5628/**
5629 * xmlSchemaParseGroup:
5630 * @ctxt: a schema validation context
5631 * @schema: the schema being built
5632 * @node: a subtree containing XML Schema informations
5633 *
5634 * parse a XML schema Group definition
5635 * *WARNING* this interface is highly subject to change
5636 *
William M. Bracke7091952004-05-11 15:09:58 +00005637 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005638 * 1 in case of success.
5639 */
5640static xmlSchemaTypePtr
5641xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005642 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005643{
5644 xmlSchemaTypePtr type, subtype;
5645 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005646 const xmlChar *name;
5647 const xmlChar *ref = NULL, *refNs = NULL;
5648 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00005649
5650 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5651 return (NULL);
5652
5653
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005654 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005656 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5657 if (ref == NULL) {
5658 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005659 XML_SCHEMAP_GROUP_NONAME_NOREF,
5660 "Group definition or particle: One of the attributes \"name\" "
5661 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 return (NULL);
5663 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005664 if (refNs == NULL)
5665 refNs = schema->targetNamespace;
5666 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5667 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005669 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 if (type == NULL)
5671 return (NULL);
5672 type->node = node;
5673 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005674 if (topLevel)
5675 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005676 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005677 type->ref = ref;
5678 type->refNs = refNs;
5679 type->minOccurs = xmlGetMinOccurs(ctxt, node);
5680 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
5681
5682 child = node->children;
5683 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005684 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5685 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005686 }
5687 subtype = NULL;
5688 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 subtype = (xmlSchemaTypePtr)
5690 xmlSchemaParseAll(ctxt, schema, child);
5691 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005692 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005693 subtype = xmlSchemaParseChoice(ctxt, schema, child);
5694 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005695 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 subtype = (xmlSchemaTypePtr)
5697 xmlSchemaParseSequence(ctxt, schema, child);
5698 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005699 }
5700 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005701 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005702 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005703 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005705 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005706 }
5707
5708 return (type);
5709}
5710
5711/**
5712 * xmlSchemaParseAll:
5713 * @ctxt: a schema validation context
5714 * @schema: the schema being built
5715 * @node: a subtree containing XML Schema informations
5716 *
5717 * parse a XML schema All definition
5718 * *WARNING* this interface is highly subject to change
5719 *
William M. Bracke7091952004-05-11 15:09:58 +00005720 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005721 * 1 in case of success.
5722 */
5723static xmlSchemaTypePtr
5724xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005725 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005726{
5727 xmlSchemaTypePtr type, subtype, last = NULL;
5728 xmlNodePtr child = NULL;
5729 xmlChar name[30];
5730
5731 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5732 return (NULL);
5733
5734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005735 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005736 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005737 if (type == NULL)
5738 return (NULL);
5739 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00005740 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005741 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005742 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005743 if (type->minOccurs > 1)
5744 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005745 "<all>: The value of the attribute \"minOccurs\" is invalid. "
5746 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005747 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005748 if (type->maxOccurs > 1)
5749 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005750 "<all>: The value of the attribute \"maxOccurs\" is invalid. "
5751 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005752
5753 child = node->children;
5754 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005755 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5756 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 }
5758 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005759 subtype = (xmlSchemaTypePtr)
5760 xmlSchemaParseElement(ctxt, schema, child, 0);
5761 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00005762 if (subtype->minOccurs > 1)
5763 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005765 NULL, NULL);
5766 if (subtype->maxOccurs > 1)
5767 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005768 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005769 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005770 if (last == NULL) {
5771 type->subtypes = subtype;
5772 last = subtype;
5773 } else {
5774 last->next = subtype;
5775 last = subtype;
5776 }
5777 last->next = NULL;
5778 }
5779 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 }
5781 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005782 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005783 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005785 }
5786
5787 return (type);
5788}
5789
5790/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005791 * xmlSchemaCleanupDoc:
5792 * @ctxt: a schema validation context
5793 * @node: the root of the document.
5794 *
5795 * removes unwanted nodes in a schemas document tree
5796 */
5797static void
5798xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
5799{
5800 xmlNodePtr delete, cur;
5801
5802 if ((ctxt == NULL) || (root == NULL)) return;
5803
5804 /*
5805 * Remove all the blank text nodes
5806 */
5807 delete = NULL;
5808 cur = root;
5809 while (cur != NULL) {
5810 if (delete != NULL) {
5811 xmlUnlinkNode(delete);
5812 xmlFreeNode(delete);
5813 delete = NULL;
5814 }
5815 if (cur->type == XML_TEXT_NODE) {
5816 if (IS_BLANK_NODE(cur)) {
5817 if (xmlNodeGetSpacePreserve(cur) != 1) {
5818 delete = cur;
5819 }
5820 }
5821 } else if ((cur->type != XML_ELEMENT_NODE) &&
5822 (cur->type != XML_CDATA_SECTION_NODE)) {
5823 delete = cur;
5824 goto skip_children;
5825 }
5826
5827 /*
5828 * Skip to next node
5829 */
5830 if (cur->children != NULL) {
5831 if ((cur->children->type != XML_ENTITY_DECL) &&
5832 (cur->children->type != XML_ENTITY_REF_NODE) &&
5833 (cur->children->type != XML_ENTITY_NODE)) {
5834 cur = cur->children;
5835 continue;
5836 }
5837 }
5838 skip_children:
5839 if (cur->next != NULL) {
5840 cur = cur->next;
5841 continue;
5842 }
5843
5844 do {
5845 cur = cur->parent;
5846 if (cur == NULL)
5847 break;
5848 if (cur == root) {
5849 cur = NULL;
5850 break;
5851 }
5852 if (cur->next != NULL) {
5853 cur = cur->next;
5854 break;
5855 }
5856 } while (cur != NULL);
5857 }
5858 if (delete != NULL) {
5859 xmlUnlinkNode(delete);
5860 xmlFreeNode(delete);
5861 delete = NULL;
5862 }
5863}
5864
William M. Brack2f2a6632004-08-20 23:09:47 +00005865
5866/**
5867 * xmlSchemaImportSchema
5868 *
5869 * @ctxt: a schema validation context
5870 * @schemaLocation: an URI defining where to find the imported schema
5871 *
5872 * import a XML schema
5873 * *WARNING* this interface is highly subject to change
5874 *
5875 * Returns -1 in case of error and 1 in case of success.
5876 */
5877#if 0
5878static xmlSchemaImportPtr
5879xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
5880 const xmlChar *schemaLocation)
5881{
5882 xmlSchemaImportPtr import;
5883 xmlSchemaParserCtxtPtr newctxt;
5884
5885 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5886 if (newctxt == NULL) {
5887 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
5888 NULL);
5889 return (NULL);
5890 }
5891 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
5892 /* Keep the same dictionnary for parsing, really */
5893 xmlDictReference(ctxt->dict);
5894 newctxt->dict = ctxt->dict;
5895 newctxt->includes = 0;
5896 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
5897
5898 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
5899 ctxt->userData);
5900
5901 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
5902 if (import == NULL) {
5903 xmlSchemaPErrMemory(NULL, "allocating imported schema",
5904 NULL);
5905 xmlSchemaFreeParserCtxt(newctxt);
5906 return (NULL);
5907 }
5908
5909 memset(import, 0, sizeof(xmlSchemaImport));
5910 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
5911 import->schema = xmlSchemaParse(newctxt);
5912
5913 if (import->schema == NULL) {
5914 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005915 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00005916 "Failed to import schema from location \"%s\".\n",
5917 schemaLocation, NULL);
5918
5919 xmlSchemaFreeParserCtxt(newctxt);
5920 /* The schemaLocation is held by the dictionary.
5921 if (import->schemaLocation != NULL)
5922 xmlFree((xmlChar *)import->schemaLocation);
5923 */
5924 xmlFree(import);
5925 return NULL;
5926 }
5927
5928 xmlSchemaFreeParserCtxt(newctxt);
5929 return import;
5930}
5931#endif
5932
5933static void
5934xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
5935{
5936 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5937 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
5938
5939 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5940 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
5941
5942 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
5943 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
5944 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
5945 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
5946 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
5947 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
5948 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
5949 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
5950
5951 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
5952 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
5953 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
5954 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
5955 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
5956 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
5957}
5958
5959static void
5960xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
5961 xmlSchemaPtr schema,
5962 xmlNodePtr node)
5963{
5964 xmlAttrPtr attr;
5965 const xmlChar *val;
5966
5967 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
5968 if (attr != NULL) {
5969 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5970 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
5971 XML_SCHEMAS_QUALIF_ELEM) != 0) {
5972 xmlSchemaPSimpleTypeErr(ctxt,
5973 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
5974 NULL, NULL, (xmlNodePtr) attr, NULL,
5975 "(qualified | unqualified)", val, NULL, NULL, NULL);
5976 }
5977 }
5978
5979 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
5980 if (attr != NULL) {
5981 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5982 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
5983 XML_SCHEMAS_QUALIF_ATTR) != 0) {
5984 xmlSchemaPSimpleTypeErr(ctxt,
5985 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
5986 NULL, NULL, (xmlNodePtr) attr, NULL,
5987 "(qualified | unqualified)", val, NULL, NULL, NULL);
5988 }
5989 }
5990
5991 attr = xmlSchemaGetPropNode(node, "finalDefault");
5992 if (attr != NULL) {
5993 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5994 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
5995 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
5996 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
5997 -1,
5998 XML_SCHEMAS_FINAL_DEFAULT_LIST,
5999 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6000 xmlSchemaPSimpleTypeErr(ctxt,
6001 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6002 NULL, NULL, (xmlNodePtr) attr, NULL,
6003 "(#all | List of (extension | restriction | list | union))",
6004 val, NULL, NULL, NULL);
6005 }
6006 }
6007
6008 attr = xmlSchemaGetPropNode(node, "blockDefault");
6009 if (attr != NULL) {
6010 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6011 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6012 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6013 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6014 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6015 xmlSchemaPSimpleTypeErr(ctxt,
6016 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6017 NULL, NULL, (xmlNodePtr) attr, NULL,
6018 "(#all | List of (extension | restriction | substitution))",
6019 val, NULL, NULL, NULL);
6020 }
6021 }
6022}
6023
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006024/**
6025 * xmlSchemaParseSchemaTopLevel:
6026 * @ctxt: a schema validation context
6027 * @schema: the schemas
6028 * @nodes: the list of top level nodes
6029 *
6030 * Returns the internal XML Schema structure built from the resource or
6031 * NULL in case of error
6032 */
6033static void
6034xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6035 xmlSchemaPtr schema, xmlNodePtr nodes)
6036{
6037 xmlNodePtr child;
6038 xmlSchemaAnnotPtr annot;
6039
6040 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6041 return;
6042
6043 child = nodes;
6044 while ((IS_SCHEMA(child, "include")) ||
6045 (IS_SCHEMA(child, "import")) ||
6046 (IS_SCHEMA(child, "redefine")) ||
6047 (IS_SCHEMA(child, "annotation"))) {
6048 if (IS_SCHEMA(child, "annotation")) {
6049 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6050 if (schema->annot == NULL)
6051 schema->annot = annot;
6052 else
6053 xmlSchemaFreeAnnot(annot);
6054 } else if (IS_SCHEMA(child, "import")) {
6055 xmlSchemaParseImport(ctxt, schema, child);
6056 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006057 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006058 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006059 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006060 } else if (IS_SCHEMA(child, "redefine")) {
6061 TODO
6062 }
6063 child = child->next;
6064 }
6065 while (child != NULL) {
6066 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006067 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006068 child = child->next;
6069 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006070 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006071 child = child->next;
6072 } else if (IS_SCHEMA(child, "element")) {
6073 xmlSchemaParseElement(ctxt, schema, child, 1);
6074 child = child->next;
6075 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006076 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006077 child = child->next;
6078 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006079 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006080 child = child->next;
6081 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006082 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006083 child = child->next;
6084 } else if (IS_SCHEMA(child, "notation")) {
6085 xmlSchemaParseNotation(ctxt, schema, child);
6086 child = child->next;
6087 } else {
6088 xmlSchemaPErr2(ctxt, NULL, child,
6089 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006090 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006091 child->name, NULL);
6092 child = child->next;
6093 }
6094 while (IS_SCHEMA(child, "annotation")) {
6095 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6096 if (schema->annot == NULL)
6097 schema->annot = annot;
6098 else
6099 xmlSchemaFreeAnnot(annot);
6100 child = child->next;
6101 }
6102 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006103 ctxt->parentItem = NULL;
6104 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006105}
6106
William M. Brack2f2a6632004-08-20 23:09:47 +00006107
6108/**
6109 * xmlSchemaParseImport:
6110 * @ctxt: a schema validation context
6111 * @schema: the schema being built
6112 * @node: a subtree containing XML Schema informations
6113 *
6114 * parse a XML schema Import definition
6115 * *WARNING* this interface is highly subject to change
6116 *
6117 * Returns 0 in case of success, a positive error code if
6118 * not valid and -1 in case of an internal error.
6119 */
6120static int
6121xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6122 xmlNodePtr node)
6123{
6124 xmlNodePtr child = NULL;
6125 xmlSchemaImportPtr import = NULL;
6126 const xmlChar *namespace = NULL, *ns;
6127 const xmlChar *schemaLocation = NULL;
6128 const xmlChar *targetNamespace, *oldTNS, *url;
6129 xmlAttrPtr attr;
6130 xmlDocPtr doc;
6131 xmlNodePtr root;
6132 xmlChar *base = NULL;
6133 xmlChar *URI = NULL;
6134 int flags;
6135 xmlParserCtxtPtr parserCtxt;
6136
6137
6138 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6139 return (-1);
6140
6141 /*
6142 * Check for illegal attributes.
6143 */
6144 attr = node->properties;
6145 while (attr != NULL) {
6146 if (attr->ns == NULL) {
6147 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6148 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6149 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6150 xmlSchemaPIllegalAttrErr(ctxt,
6151 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6152 NULL, NULL, attr);
6153 }
6154 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6155 xmlSchemaPIllegalAttrErr(ctxt,
6156 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6157 NULL, NULL, attr);
6158 }
6159 attr = attr->next;
6160 }
6161 /*
6162 * Extract and validate attributes.
6163 */
6164 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6165 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6166 &namespace) != 0) {
6167 xmlSchemaPSimpleTypeErr(ctxt,
6168 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6169 NULL, NULL, node,
6170 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6171 NULL, namespace, NULL, NULL, NULL);
6172 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6173 }
6174
6175 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6176 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6177 &schemaLocation) != 0) {
6178 xmlSchemaPSimpleTypeErr(ctxt,
6179 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6180 NULL, NULL, node,
6181 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6182 NULL, namespace, NULL, NULL, NULL);
6183 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6184 }
6185 /*
6186 * And now for the children...
6187 */
6188 child = node->children;
6189 if (IS_SCHEMA(child, "annotation")) {
6190 /*
6191 * the annotation here is simply discarded ...
6192 */
6193 child = child->next;
6194 }
6195 if (child != NULL) {
6196 xmlSchemaPContentErr(ctxt,
6197 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6198 NULL, NULL, node, child, NULL,
6199 "(annotation?)");
6200 }
6201 /*
6202 * Apply additional constraints.
6203 */
6204 if (namespace != NULL) {
6205 /*
6206 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6207 * must not match the ·actual value· of the enclosing <schema>'s
6208 * targetNamespace [attribute].
6209 */
6210 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6211 xmlSchemaPCustomErr(ctxt,
6212 XML_SCHEMAP_SRC_IMPORT_1_1,
6213 NULL, NULL, node,
6214 "The value of the attribute 'namespace' must not match "
6215 "the target namespace '%s' of the importing schema",
6216 schema->targetNamespace);
6217 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6218 }
6219 } else {
6220 /*
6221 * 1.2 If the namespace [attribute] is not present, then the enclosing
6222 * <schema> must have a targetNamespace [attribute].
6223 */
6224 if (schema->targetNamespace == NULL) {
6225 xmlSchemaPCustomErr(ctxt,
6226 XML_SCHEMAP_SRC_IMPORT_1_2,
6227 NULL, NULL, node,
6228 "The attribute 'namespace' must be existent if "
6229 "the importing schema has no target namespace",
6230 NULL);
6231 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6232 }
6233 }
6234
6235 /*
6236 * Given that the schemaLocation [attribute] is only a hint, it is open
6237 * to applications to ignore all but the first <import> for a given
6238 * namespace, regardless of the ·actual value· of schemaLocation, but
6239 * such a strategy risks missing useful information when new
6240 * schemaLocations are offered.
6241 *
6242 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6243 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6244 * valid or not.
6245 * We will follow XSV here.
6246 */
6247 if (schemaLocation == NULL) {
6248 /*
6249 * Schema Document Location Strategy:
6250 *
6251 * 3 Based on the namespace name, identify an existing schema document,
6252 * either as a resource which is an XML document or a <schema> element
6253 * information item, in some local schema repository;
6254 *
6255 * 5 Attempt to resolve the namespace name to locate such a resource.
6256 *
6257 * NOTE: Those stategies are not supported, so we will skip.
6258 */
6259 return (0);
6260 }
6261 if (namespace == NULL)
6262 ns = XML_SCHEMAS_NO_NAMESPACE;
6263 else
6264 ns = namespace;
6265
6266 import = xmlHashLookup(schema->schemasImports, ns);
6267 if (import != NULL) {
6268 /*
6269 * There was a valid resource for the specified namespace already
6270 * defined, so skip.
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006271 * TODO: This might be changed someday to allow import of
6272 * components from multiple documents for a single target namespace.
William M. Brack2f2a6632004-08-20 23:09:47 +00006273 */
6274 return (0);
6275 }
6276 /*
6277 * Schema Document Location Strategy:
6278 *
6279 * 2 Based on the location URI, identify an existing schema document,
6280 * either as a resource which is an XML document or a <schema> element
6281 * information item, in some local schema repository;
6282 *
6283 * 4 Attempt to resolve the location URI, to locate a resource on the
6284 * web which is or contains or references a <schema> element;
6285 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6286 *
6287 */
6288
6289 base = xmlNodeGetBase(node->doc, node);
6290 if (base == NULL) {
6291 URI = xmlBuildURI(schemaLocation, node->doc->URL);
6292 } else {
6293 URI = xmlBuildURI(schemaLocation, base);
6294 xmlFree(base);
6295 }
6296 if (URI != NULL) {
6297 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
6298 xmlFree(URI);
6299 }
6300
6301 parserCtxt = xmlNewParserCtxt();
6302 if (parserCtxt == NULL) {
6303 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6304 "allocating a parser context", NULL);
6305 return(-1);
6306 }
6307
6308 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
6309 NULL, SCHEMAS_PARSE_OPTIONS);
6310
6311 /*
6312 * 2.1 The referent is (a fragment of) a resource which is an
6313 * XML document (see clause 1.1), which in turn corresponds to
6314 * a <schema> element information item in a well-formed information
6315 * set, which in turn corresponds to a valid schema.
6316 * TODO: What to do with the "fragment" stuff?
6317 *
6318 * 2.2 The referent is a <schema> element information item in
6319 * a well-formed information set, which in turn corresponds
6320 * to a valid schema.
6321 * NOTE: 2.2 won't apply, since only XML documents will be processed
6322 * here.
6323 */
6324 if (doc == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006325 xmlErrorPtr lerr;
William M. Brack2f2a6632004-08-20 23:09:47 +00006326 /*
6327 * It is *not* an error for the application schema reference
6328 * strategy to fail.
6329 *
6330 * If the doc is NULL and the parser error is an IO error we
6331 * will assume that the resource could not be located or accessed.
6332 *
6333 * TODO: Try to find specific error codes to react only on
6334 * localisation failures.
6335 *
6336 * TODO, FIXME: Check the spec: is a namespace added to the imported
6337 * namespaces, even if the schemaLocation did not provide
6338 * a resource? I guess so, since omitting the "schemaLocation"
6339 * attribute, imports a namespace as well.
6340 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006341 lerr = xmlGetLastError();
6342 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006343 xmlFreeParserCtxt(parserCtxt);
6344 return(0);
6345 }
6346
6347 xmlSchemaPCustomErr(ctxt,
6348 XML_SCHEMAP_SRC_IMPORT_2_1,
6349 NULL, NULL, node,
6350 "Failed to parse the resource '%s' for import",
6351 schemaLocation);
6352 xmlFreeParserCtxt(parserCtxt);
6353 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6354 }
6355 xmlFreeParserCtxt(parserCtxt);
6356
6357 root = xmlDocGetRootElement(doc);
6358 if (root == NULL) {
6359 xmlSchemaPCustomErr(ctxt,
6360 XML_SCHEMAP_SRC_IMPORT_2_1,
6361 NULL, NULL, node,
6362 "The XML document '%s' to be imported has no document "
6363 "element", schemaLocation);
6364 xmlFreeDoc(doc);
6365 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6366 }
6367
6368 xmlSchemaCleanupDoc(ctxt, root);
6369
6370 if (!IS_SCHEMA(root, "schema")) {
6371 xmlSchemaPCustomErr(ctxt,
6372 XML_SCHEMAP_SRC_IMPORT_2_1,
6373 NULL, NULL, node,
6374 "The XML document '%s' to be imported is not a XML schema document",
6375 schemaLocation);
6376 xmlFreeDoc(doc);
6377 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6378 }
6379 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6380 /*
6381 * Schema Representation Constraint: Import Constraints and Semantics
6382 */
6383 if (namespace == NULL) {
6384 if (targetNamespace != NULL) {
6385 xmlSchemaPCustomErr(ctxt,
6386 XML_SCHEMAP_SRC_IMPORT_3_2,
6387 NULL, NULL, node,
6388 "No 'namespace' attribute was "
6389 "specified, thus the XML schema to be imported "
6390 "must have no target namespace", NULL);
6391 xmlFreeDoc(doc);
6392 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6393 }
6394 } else {
6395 if (targetNamespace == NULL) {
6396 xmlSchemaPCustomErr(ctxt,
6397 XML_SCHEMAP_SRC_IMPORT_3_1,
6398 NULL, NULL, node,
6399 "The attribute 'namespace' requires the XML schema to be "
6400 "imported to have a target namespace of '%s'", namespace);
6401 xmlFreeDoc(doc);
6402 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6403 } else if (!xmlStrEqual(targetNamespace, namespace)) {
6404 xmlSchemaPCustomErrExt(ctxt,
6405 XML_SCHEMAP_SRC_IMPORT_3_1,
6406 NULL, NULL, node,
6407 "The value '%s' of the attribute 'namespace' is not "
6408 "identical to the target namespace '%s' of the "
6409 "XML schema to be imported",
6410 namespace, targetNamespace, NULL);
6411 xmlFreeDoc(doc);
6412 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6413 }
6414 }
6415 /*
6416 * Finally, import the schema.
6417 */
6418 if (schema->schemasImports == NULL) {
6419 schema->schemasImports = xmlHashCreate(10);
6420 if (schema->schemasImports == NULL) {
6421 xmlSchemaPErr2(ctxt, node, child,
6422 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6423 "Internal error: failed to build import table.\n",
6424 NULL, NULL);
6425 return (-1);
6426 }
6427 }
6428 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6429 if (import == NULL) {
6430 xmlSchemaPErrMemory(NULL, "allocating imported schema", NULL);
6431 xmlFreeDoc(doc);
6432 return (-1);
6433 }
6434 memset(import, 0, sizeof(xmlSchemaImport));
6435 import->schemaLocation = schemaLocation;
6436 import->doc = doc;
6437 xmlHashAddEntry(schema->schemasImports, ns, import);
6438 /*
6439 * Save and reset the context & schema.
6440 */
6441 url = ctxt->URL;
6442 /* TODO: Check this. */
6443 ctxt->URL = schemaLocation;
6444 flags = schema->flags;
6445 oldTNS = schema->targetNamespace;
6446
6447 xmlSchemaClearSchemaDefaults(schema);
6448 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6449 schema->targetNamespace = targetNamespace;
6450 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6451
6452 /*
6453 * Restore the context & schema.
6454 */
6455 schema->flags = flags;
6456 schema->targetNamespace = oldTNS;
6457 ctxt->URL = url;
6458
6459 return (1);
6460}
6461
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006462/**
6463 * xmlSchemaParseInclude:
6464 * @ctxt: a schema validation context
6465 * @schema: the schema being built
6466 * @node: a subtree containing XML Schema informations
6467 *
6468 * parse a XML schema Include definition
6469 *
William M. Bracke7091952004-05-11 15:09:58 +00006470 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006471 * 1 in case of success.
6472 */
6473static int
6474xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6475 xmlNodePtr node)
6476{
6477 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006479 xmlDocPtr doc;
6480 xmlNodePtr root;
6481 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006483 xmlAttrPtr attr;
6484 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006485
6486
6487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6488 return (-1);
6489
6490 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006491 * Check for illegal attributes.
6492 */
6493 attr = node->properties;
6494 while (attr != NULL) {
6495 if (attr->ns == NULL) {
6496 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6497 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6498 xmlSchemaPIllegalAttrErr(ctxt,
6499 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6500 NULL, NULL, attr);
6501 }
6502 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6503 xmlSchemaPIllegalAttrErr(ctxt,
6504 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6505 NULL, NULL, attr);
6506 }
6507 attr = attr->next;
6508 }
6509 /*
6510 * Extract and validate attributes.
6511 */
6512 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006513 * Preliminary step, extract the URI-Reference for the include and
6514 * make an URI from the base.
6515 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006516 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6517 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006518 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006519 xmlChar *uri = NULL;
6520
6521 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6522 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6523 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006524 base = xmlNodeGetBase(node->doc, node);
6525 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006526 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006527 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006528 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006529 xmlFree(base);
6530 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006531 if (uri != NULL) {
6532 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6533 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006534 }
6535 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006536 xmlSchemaPMissingAttrErr(ctxt,
6537 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6538 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006539 return (-1);
6540 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006541 /*
6542 * And now for the children...
6543 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006544 child = node->children;
6545 while (IS_SCHEMA(child, "annotation")) {
6546 /*
6547 * the annotations here are simply discarded ...
6548 */
6549 child = child->next;
6550 }
6551 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006552 xmlSchemaPContentErr(ctxt,
6553 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6554 NULL, NULL, node, child, NULL,
6555 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006556 }
6557
6558 /*
6559 * First step is to parse the input document into an DOM/Infoset
6560 */
6561 doc = xmlReadFile((const char *) schemaLocation, NULL,
6562 SCHEMAS_PARSE_OPTIONS);
6563 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006564 /*
6565 * TODO: It is not an error for the ·actual value· of the
6566 * schemaLocation [attribute] to fail to resolve it all, in which
6567 * case no corresponding inclusion is performed.
6568 * So do we need a warning report here?
6569 */
6570 xmlSchemaPCustomErr(ctxt,
6571 XML_SCHEMAP_FAILED_LOAD,
6572 NULL, NULL, node,
6573 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006574 return(-1);
6575 }
6576
6577 /*
6578 * Then extract the root of the schema
6579 */
6580 root = xmlDocGetRootElement(doc);
6581 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006582 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006583 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006584 NULL, NULL, node,
6585 "The included document '%s' has no document "
6586 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006587 xmlFreeDoc(doc);
6588 return (-1);
6589 }
6590
6591 /*
6592 * Remove all the blank text nodes
6593 */
6594 xmlSchemaCleanupDoc(ctxt, root);
6595
6596 /*
6597 * Check the schemas top level element
6598 */
6599 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006600 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006602 NULL, NULL, node,
6603 "The document '%s' to be included is not a schema document",
6604 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006605 xmlFreeDoc(doc);
6606 return (-1);
6607 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608
William M. Brack2f2a6632004-08-20 23:09:47 +00006609 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006610 /*
6611 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6612 * value· is identical to the ·actual value· of the targetNamespace
6613 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6614 */
6615 if (targetNamespace != NULL) {
6616 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006617 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006618 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006619 NULL, NULL, node,
6620 "The target namespace of the included schema "
6621 "'%s' has to be absent, since the including schema "
6622 "has no target namespace",
6623 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006624 xmlFreeDoc(doc);
6625 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006626 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6627 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006628 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006629 NULL, NULL, node,
6630 "The target namespace '%s' of the included schema '%s' "
6631 "differs from '%s' of the including schema",
6632 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006633 xmlFreeDoc(doc);
6634 return (-1);
6635 }
6636 } else if (schema->targetNamespace != NULL) {
6637 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
6638 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
6639 } else
6640 wasConvertingNs = 1;
6641 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006642 /*
6643 * register the include
6644 */
6645 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
6646 if (include == NULL) {
6647 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
6648 xmlFreeDoc(doc);
6649 return (-1);
6650 }
6651
6652 memset(include, 0, sizeof(xmlSchemaInclude));
6653 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6654 include->doc = doc;
6655 include->next = schema->includes;
6656 schema->includes = include;
6657
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006658 /*
6659 * parse the declarations in the included file like if they
6660 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006661 */
6662 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006663 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006664 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006665 /*
6666 * The default values ("blockDefault", "elementFormDefault", etc.)
6667 * are set to the values of the included schema and restored afterwards.
6668 */
6669 saveFlags = schema->flags;
6670 xmlSchemaClearSchemaDefaults(schema);
6671 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006672 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00006673 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006674 /*
6675 * Remove the converting flag.
6676 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006677 if ((wasConvertingNs == 0) &&
6678 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006679 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006680 return (1);
6681}
6682
6683/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006684 * xmlSchemaParseChoice:
6685 * @ctxt: a schema validation context
6686 * @schema: the schema being built
6687 * @node: a subtree containing XML Schema informations
6688 *
6689 * parse a XML schema Choice definition
6690 * *WARNING* this interface is highly subject to change
6691 *
William M. Bracke7091952004-05-11 15:09:58 +00006692 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 * 1 in case of success.
6694 */
6695static xmlSchemaTypePtr
6696xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006697 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006698{
6699 xmlSchemaTypePtr type, subtype, last = NULL;
6700 xmlNodePtr child = NULL;
6701 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006702 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703
6704 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6705 return (NULL);
6706
6707
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006708 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006709 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006710 if (type == NULL)
6711 return (NULL);
6712 type->node = node;
6713 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006714 /*
6715 * Check for illegal attributes.
6716 */
6717 attr = node->properties;
6718 while (attr != NULL) {
6719 if (attr->ns == NULL) {
6720 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6721 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6722 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6723 xmlSchemaPIllegalAttrErr(ctxt,
6724 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6725 NULL, type, attr);
6726 }
6727 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6728 xmlSchemaPIllegalAttrErr(ctxt,
6729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6730 NULL, type, attr);
6731 }
6732 attr = attr->next;
6733 }
6734 /*
6735 * Extract and validate attributes.
6736 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006737 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006738 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6739 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brack2f2a6632004-08-20 23:09:47 +00006740 /*
6741 * And now for the children...
6742 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 child = node->children;
6744 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006745 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6746 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006747 }
6748 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006749 (IS_SCHEMA(child, "group")) ||
6750 (IS_SCHEMA(child, "any")) ||
6751 (IS_SCHEMA(child, "choice")) ||
6752 (IS_SCHEMA(child, "sequence"))) {
6753 subtype = NULL;
6754 if (IS_SCHEMA(child, "element")) {
6755 subtype = (xmlSchemaTypePtr)
6756 xmlSchemaParseElement(ctxt, schema, child, 0);
6757 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006758 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006759 } else if (IS_SCHEMA(child, "any")) {
6760 subtype = xmlSchemaParseAny(ctxt, schema, child);
6761 } else if (IS_SCHEMA(child, "sequence")) {
6762 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6763 } else if (IS_SCHEMA(child, "choice")) {
6764 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6765 }
6766 if (subtype != NULL) {
6767 if (last == NULL) {
6768 type->subtypes = subtype;
6769 last = subtype;
6770 } else {
6771 last->next = subtype;
6772 last = subtype;
6773 }
6774 last->next = NULL;
6775 }
6776 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006777 }
6778 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006779 /* TODO: error code. */
6780 xmlSchemaPContentErr(ctxt,
6781 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
6782 NULL, type, node, child, NULL,
6783 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006784 }
6785
6786 return (type);
6787}
6788
6789/**
6790 * xmlSchemaParseSequence:
6791 * @ctxt: a schema validation context
6792 * @schema: the schema being built
6793 * @node: a subtree containing XML Schema informations
6794 *
6795 * parse a XML schema Sequence definition
6796 * *WARNING* this interface is highly subject to change
6797 *
William M. Bracke7091952004-05-11 15:09:58 +00006798 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006799 * 1 in case of success.
6800 */
6801static xmlSchemaTypePtr
6802xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006803 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006804{
6805 xmlSchemaTypePtr type, subtype, last = NULL;
6806 xmlNodePtr child = NULL;
6807 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006808 xmlAttrPtr attr;
6809 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006810
6811 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6812 return (NULL);
6813
William M. Brack2f2a6632004-08-20 23:09:47 +00006814 oldcontainer = ctxt->container;
6815 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
6816 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006817 if (type == NULL)
6818 return (NULL);
6819 type->node = node;
6820 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006821 /*
6822 * Check for illegal attributes.
6823 */
6824 attr = node->properties;
6825 while (attr != NULL) {
6826 if (attr->ns == NULL) {
6827 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6828 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6829 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6830 xmlSchemaPIllegalAttrErr(ctxt,
6831 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6832 NULL, type, attr);
6833 }
6834 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6835 xmlSchemaPIllegalAttrErr(ctxt,
6836 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6837 NULL, type, attr);
6838 }
6839 attr = attr->next;
6840 }
6841 /*
6842 * Extract and validate attributes.
6843 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006844 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006845 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6846 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brack2f2a6632004-08-20 23:09:47 +00006847 /*
6848 * And now for the children...
6849 */
6850 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006851 child = node->children;
6852 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006853 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6854 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006855 }
6856 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006857 (IS_SCHEMA(child, "group")) ||
6858 (IS_SCHEMA(child, "any")) ||
6859 (IS_SCHEMA(child, "choice")) ||
6860 (IS_SCHEMA(child, "sequence"))) {
6861 subtype = NULL;
6862 if (IS_SCHEMA(child, "element")) {
6863 subtype = (xmlSchemaTypePtr)
6864 xmlSchemaParseElement(ctxt, schema, child, 0);
6865 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006866 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006867 } else if (IS_SCHEMA(child, "any")) {
6868 subtype = xmlSchemaParseAny(ctxt, schema, child);
6869 } else if (IS_SCHEMA(child, "choice")) {
6870 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6871 } else if (IS_SCHEMA(child, "sequence")) {
6872 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6873 }
6874 if (subtype != NULL) {
6875 if (last == NULL) {
6876 type->subtypes = subtype;
6877 last = subtype;
6878 } else {
6879 last->next = subtype;
6880 last = subtype;
6881 }
6882 last->next = NULL;
6883 }
6884 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006885 }
6886 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006887 xmlSchemaPContentErr(ctxt,
6888 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
6889 NULL, type, node, child, NULL,
6890 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006892 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006893
6894 return (type);
6895}
6896
6897/**
6898 * xmlSchemaParseRestriction:
6899 * @ctxt: a schema validation context
6900 * @schema: the schema being built
6901 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00006902 *
6903 * parse a XML schema Restriction definition
6904 * *WARNING* this interface is highly subject to change
6905 *
6906 * Returns the type definition or NULL in case of error
6907 */
6908static xmlSchemaTypePtr
6909xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006910 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006911{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006912 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006913 xmlNodePtr child = NULL;
6914 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006915 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00006916 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006917
6918 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6919 return (NULL);
6920
6921 oldcontainer = ctxt->container;
6922
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
6924 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006925 if (type == NULL)
6926 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006927 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006928 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006929 /*
6930 * Check for illegal attributes.
6931 */
6932 attr = node->properties;
6933 while (attr != NULL) {
6934 if (attr->ns == NULL) {
6935 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6936 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
6937 xmlSchemaPIllegalAttrErr(ctxt,
6938 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6939 NULL, type, attr);
6940 }
6941 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6942 xmlSchemaPIllegalAttrErr(ctxt,
6943 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6944 NULL, type, attr);
6945 }
6946 attr = attr->next;
6947 }
6948 /*
6949 * Extract and validate attributes.
6950 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006951 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006952 /*
6953 * Attribute "base".
6954 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00006956 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00006957 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
6958 /* TODO: Think about the error code. */
6959 xmlSchemaPMissingAttrErr(ctxt,
6960 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
6961 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006963 /*
6964 * And now for the children...
6965 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006966 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 child = node->children;
6968 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006969 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6970 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006971 }
6972 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006973 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
6974 if (IS_SCHEMA(child, "all")) {
6975 subtype = (xmlSchemaTypePtr)
6976 xmlSchemaParseAll(ctxt, schema, child);
6977 child = child->next;
6978 type->subtypes = subtype;
6979 } else if (IS_SCHEMA(child, "choice")) {
6980 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6981 child = child->next;
6982 type->subtypes = subtype;
6983 } else if (IS_SCHEMA(child, "sequence")) {
6984 subtype = (xmlSchemaTypePtr)
6985 xmlSchemaParseSequence(ctxt, schema, child);
6986 child = child->next;
6987 type->subtypes = subtype;
6988 } else if (IS_SCHEMA(child, "group")) {
6989 subtype = (xmlSchemaTypePtr)
6990 xmlSchemaParseGroup(ctxt, schema, child, 0);
6991 child = child->next;
6992 type->subtypes = subtype;
6993 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006994 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
6995 if (IS_SCHEMA(child, "simpleType")) {
6996 if (type->base != NULL) {
6997 /*
6998 * src-restriction-base-or-simpleType
6999 * Either the base [attribute] or the simpleType [child] of the
7000 * <restriction> element must be present, but not both.
7001 */
7002 xmlSchemaPContentErr(ctxt,
7003 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7004 NULL, NULL, type->node, child,
7005 "The attribute 'base' and the <simpleType> child are "
7006 "mutually exclusive", NULL);
7007 } else {
7008 subtype = (xmlSchemaTypePtr)
7009 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7010 type->baseType = subtype;
7011 }
7012 child = child->next;
7013 }
7014 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007015 if (IS_SCHEMA(child, "simpleType")) {
7016 subtype = (xmlSchemaTypePtr)
7017 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007018 type->subtypes = subtype;
7019 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007020 }
7021 }
7022 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7023 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7024 xmlSchemaFacetPtr facet, lastfacet = NULL;
7025
Daniel Veillard01fa6152004-06-29 17:04:39 +00007026 /*
7027 * Add the facets to the parent simpleType/complexType.
7028 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007029 /*
7030 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7031 * Simple Type Definition Schema Representation Constraint:
7032 * *Single Facet Value*
7033 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007034 while ((IS_SCHEMA(child, "minInclusive")) ||
7035 (IS_SCHEMA(child, "minExclusive")) ||
7036 (IS_SCHEMA(child, "maxInclusive")) ||
7037 (IS_SCHEMA(child, "maxExclusive")) ||
7038 (IS_SCHEMA(child, "totalDigits")) ||
7039 (IS_SCHEMA(child, "fractionDigits")) ||
7040 (IS_SCHEMA(child, "pattern")) ||
7041 (IS_SCHEMA(child, "enumeration")) ||
7042 (IS_SCHEMA(child, "whiteSpace")) ||
7043 (IS_SCHEMA(child, "length")) ||
7044 (IS_SCHEMA(child, "maxLength")) ||
7045 (IS_SCHEMA(child, "minLength"))) {
7046 facet = xmlSchemaParseFacet(ctxt, schema, child);
7047 if (facet != NULL) {
7048 if (lastfacet == NULL)
7049 ctxt->ctxtType->facets = facet;
7050 else
7051 lastfacet->next = facet;
7052 lastfacet = facet;
7053 lastfacet->next = NULL;
7054 }
7055 child = child->next;
7056 }
7057 /*
7058 * Create links for derivation and validation.
7059 */
7060 if (lastfacet != NULL) {
7061 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7062
7063 facet = ctxt->ctxtType->facets;
7064 do {
7065 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7066 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007067 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007068 xmlFree(facetLink);
7069 return (NULL);
7070 }
7071 facetLink->facet = facet;
7072 facetLink->next = NULL;
7073 if (lastFacetLink == NULL)
7074 ctxt->ctxtType->facetSet = facetLink;
7075 else
7076 lastFacetLink->next = facetLink;
7077 lastFacetLink = facetLink;
7078 facet = facet->next;
7079 } while (facet != NULL);
7080 }
7081 }
7082 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
William M. Brack2f2a6632004-08-20 23:09:47 +00007083 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007084 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007085 /* TODO: Think about the error code. */
7086 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7087 xmlSchemaPContentErr(ctxt,
7088 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7089 NULL, type, node, child, NULL,
7090 "annotation?, (group | all | choice | sequence)?, "
7091 "((attribute | attributeGroup)*, anyAttribute?))");
7092 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7093 xmlSchemaPContentErr(ctxt,
7094 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7095 NULL, type, node, child, NULL,
7096 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7097 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7098 "length | minLength | maxLength | enumeration | whiteSpace | "
7099 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7100 } else {
7101 /* Simple type */
7102 xmlSchemaPContentErr(ctxt,
7103 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7104 NULL, type, node, child, NULL,
7105 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7106 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7107 "length | minLength | maxLength | enumeration | whiteSpace | "
7108 "pattern)*))");
7109 }
7110 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007111 ctxt->container = oldcontainer;
7112 return (type);
7113}
7114
7115/**
7116 * xmlSchemaParseExtension:
7117 * @ctxt: a schema validation context
7118 * @schema: the schema being built
7119 * @node: a subtree containing XML Schema informations
7120 *
7121 * parse a XML schema Extension definition
7122 * *WARNING* this interface is highly subject to change
7123 *
7124 * Returns the type definition or NULL in case of error
7125 */
7126static xmlSchemaTypePtr
7127xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007128 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007129{
7130 xmlSchemaTypePtr type, subtype;
7131 xmlNodePtr child = NULL;
7132 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007133 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007134
7135 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7136 return (NULL);
7137
7138 oldcontainer = ctxt->container;
7139
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007140 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007141 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007142 if (type == NULL)
7143 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007144 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007145 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007146 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007147 ctxt->container = name;
7148
7149 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7150 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007151 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007152 "<extension>: The attribute \"base\" is missing.\n",
7153 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007154 }
7155 child = node->children;
7156 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007157 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007159 }
7160 subtype = NULL;
7161
7162 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007163 subtype = xmlSchemaParseAll(ctxt, schema, child);
7164 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007165 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007166 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7167 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007168 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007169 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7170 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007171 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007172 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007173 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007174 }
7175 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007176 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007177 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7178 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007179 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007180 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7181 "<extension> has unexpected content.\n", type->name,
7182 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007183 }
7184 ctxt->container = oldcontainer;
7185 return (type);
7186}
7187
7188/**
7189 * xmlSchemaParseSimpleContent:
7190 * @ctxt: a schema validation context
7191 * @schema: the schema being built
7192 * @node: a subtree containing XML Schema informations
7193 *
7194 * parse a XML schema SimpleContent definition
7195 * *WARNING* this interface is highly subject to change
7196 *
7197 * Returns the type definition or NULL in case of error
7198 */
7199static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007200xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7201 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007202{
7203 xmlSchemaTypePtr type, subtype;
7204 xmlNodePtr child = NULL;
7205 xmlChar name[30];
7206
7207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7208 return (NULL);
7209
William M. Bracke7091952004-05-11 15:09:58 +00007210 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007211 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007212 if (type == NULL)
7213 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007214 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007215 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007216 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007217
7218 child = node->children;
7219 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007220 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7221 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007222 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007223 ctxt->parentItem = type;
7224 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007225 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007226 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007227 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007229 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007230 subtype = (xmlSchemaTypePtr)
7231 xmlSchemaParseExtension(ctxt, schema, child);
7232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007233 }
7234 type->subtypes = subtype;
7235 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007237 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7238 "<simpleContent> has unexpected content.\n",
7239 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007240 }
7241 return (type);
7242}
7243
7244/**
7245 * xmlSchemaParseComplexContent:
7246 * @ctxt: a schema validation context
7247 * @schema: the schema being built
7248 * @node: a subtree containing XML Schema informations
7249 *
7250 * parse a XML schema ComplexContent definition
7251 * *WARNING* this interface is highly subject to change
7252 *
7253 * Returns the type definition or NULL in case of error
7254 */
7255static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007256xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7257 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007258{
7259 xmlSchemaTypePtr type, subtype;
7260 xmlNodePtr child = NULL;
7261 xmlChar name[30];
7262
7263 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7264 return (NULL);
7265
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007266 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007267 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007268 if (type == NULL)
7269 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007270 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007271 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007272 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007273
7274 child = node->children;
7275 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007276 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7277 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007278 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007279 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007280 subtype = NULL;
7281 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007282 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007283 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007285 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007286 subtype = (xmlSchemaTypePtr)
7287 xmlSchemaParseExtension(ctxt, schema, child);
7288 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007289 }
7290 type->subtypes = subtype;
7291 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007292 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007293 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
7294 "<complexContent> has unexpected content.\n",
7295 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007296 }
7297 return (type);
7298}
7299
7300/**
7301 * xmlSchemaParseComplexType:
7302 * @ctxt: a schema validation context
7303 * @schema: the schema being built
7304 * @node: a subtree containing XML Schema informations
7305 *
7306 * parse a XML schema Complex Type definition
7307 * *WARNING* this interface is highly subject to change
7308 *
7309 * Returns the type definition or NULL in case of error
7310 */
7311static xmlSchemaTypePtr
7312xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007313 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007314{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007315 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007316 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007317 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00007318 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007319 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00007320
7321 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7322 return (NULL);
7323
Daniel Veillard01fa6152004-06-29 17:04:39 +00007324 ctxtType = ctxt->ctxtType;
7325
Daniel Veillard4255d502002-04-16 15:50:10 +00007326 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007327 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007328 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007329 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007330 name = (const xmlChar *)buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00007331 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007332 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007333
William M. Bracke7091952004-05-11 15:09:58 +00007334 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
William M. Brack2f2a6632004-08-20 23:09:47 +00007335 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007336 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00007338 return (NULL);
7339 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007340 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00007341 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00007342
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 type->node = node;
7344 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00007345 if (topLevel)
7346 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007347 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007348 ctxt->container = name;
7349
7350 child = node->children;
7351 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007352 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7353 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007355 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00007357 /* 3.4.3 : 2.2
7358 * Specifying mixed='true' when the <simpleContent>
7359 * alternative is chosen has no effect
7360 */
7361 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7362 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007363 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7364 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007365 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007366 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7367 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007368 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007369 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007370
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007371 if (IS_SCHEMA(child, "all")) {
7372 subtype = xmlSchemaParseAll(ctxt, schema, child);
7373 child = child->next;
7374 } else if (IS_SCHEMA(child, "choice")) {
7375 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7376 child = child->next;
7377 } else if (IS_SCHEMA(child, "sequence")) {
7378 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7379 child = child->next;
7380 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007381 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007382 child = child->next;
7383 }
7384 if (subtype != NULL)
7385 type->subtypes = subtype;
7386 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007387 }
7388 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007389 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007390 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
7391 "Complex type definition \"%s\" has unexpected content.\n",
7392 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007393 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007394 if (type->attributeWildcard != NULL)
7395 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00007396 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007397 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007398 return (type);
7399}
7400
Daniel Veillard4255d502002-04-16 15:50:10 +00007401/**
7402 * xmlSchemaParseSchema:
7403 * @ctxt: a schema validation context
7404 * @node: a subtree containing XML Schema informations
7405 *
7406 * parse a XML schema definition from a node set
7407 * *WARNING* this interface is highly subject to change
7408 *
7409 * Returns the internal XML Schema structure built from the resource or
7410 * NULL in case of error
7411 */
7412static xmlSchemaPtr
7413xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7414{
7415 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007416 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007417 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007418 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007419
7420 if ((ctxt == NULL) || (node == NULL))
7421 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007422
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007423 nberrors = ctxt->nberrors;
7424 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007425 if (IS_SCHEMA(node, "schema")) {
7426 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007427 if (schema == NULL)
7428 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007429 attr = xmlSchemaGetPropNode(node, "targetNamespace");
7430 if (attr != NULL) {
7431 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7432 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
7433 /*
7434 * TODO: Should we proceed with an invalid target namespace?
7435 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007436 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
7437 } else {
7438 schema->targetNamespace = NULL;
7439 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007440 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007441 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007442 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7443 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7444
William M. Brack2f2a6632004-08-20 23:09:47 +00007445 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007446 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
7447 } else {
7448 xmlDocPtr doc;
7449
7450 doc = node->doc;
7451
7452 if ((doc != NULL) && (doc->URL != NULL)) {
7453 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7454 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007455 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007456 } else {
7457 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7458 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007459 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007460 }
7461 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007462 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007463 if (ctxt->nberrors != 0) {
7464 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007465 xmlSchemaFree(schema);
7466 schema = NULL;
7467 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007468 }
7469 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00007470#ifdef DEBUG
7471 if (schema == NULL)
7472 xmlGenericError(xmlGenericErrorContext,
7473 "xmlSchemaParse() failed\n");
7474#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007475 return (schema);
7476}
7477
7478/************************************************************************
7479 * *
7480 * Validating using Schemas *
7481 * *
7482 ************************************************************************/
7483
7484/************************************************************************
7485 * *
7486 * Reading/Writing Schemas *
7487 * *
7488 ************************************************************************/
7489
7490/**
7491 * xmlSchemaNewParserCtxt:
7492 * @URL: the location of the schema
7493 *
7494 * Create an XML Schemas parse context for that file/resource expected
7495 * to contain an XML Schemas file.
7496 *
7497 * Returns the parser context or NULL in case of error
7498 */
7499xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007500xmlSchemaNewParserCtxt(const char *URL)
7501{
Daniel Veillard4255d502002-04-16 15:50:10 +00007502 xmlSchemaParserCtxtPtr ret;
7503
7504 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007505 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007506
7507 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7508 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007509 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007510 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007511 return (NULL);
7512 }
7513 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007514 ret->dict = xmlDictCreate();
7515 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007516 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007517 return (ret);
7518}
7519
7520/**
Daniel Veillard6045c902002-10-09 21:13:59 +00007521 * xmlSchemaNewMemParserCtxt:
7522 * @buffer: a pointer to a char array containing the schemas
7523 * @size: the size of the array
7524 *
7525 * Create an XML Schemas parse context for that memory buffer expected
7526 * to contain an XML Schemas file.
7527 *
7528 * Returns the parser context or NULL in case of error
7529 */
7530xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007531xmlSchemaNewMemParserCtxt(const char *buffer, int size)
7532{
Daniel Veillard6045c902002-10-09 21:13:59 +00007533 xmlSchemaParserCtxtPtr ret;
7534
7535 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007536 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007537
7538 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7539 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007541 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007542 return (NULL);
7543 }
7544 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7545 ret->buffer = buffer;
7546 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007547 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00007548 return (ret);
7549}
7550
7551/**
Daniel Veillard9d751502003-10-29 13:21:47 +00007552 * xmlSchemaNewDocParserCtxt:
7553 * @doc: a preparsed document tree
7554 *
7555 * Create an XML Schemas parse context for that document.
7556 * NB. The document may be modified during the parsing process.
7557 *
7558 * Returns the parser context or NULL in case of error
7559 */
7560xmlSchemaParserCtxtPtr
7561xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
7562{
7563 xmlSchemaParserCtxtPtr ret;
7564
7565 if (doc == NULL)
7566 return (NULL);
7567
7568 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7569 if (ret == NULL) {
7570 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
7571 NULL);
7572 return (NULL);
7573 }
7574 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7575 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007576 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00007577 /* The application has responsibility for the document */
7578 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00007579
7580 return (ret);
7581}
7582
7583/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007584 * xmlSchemaFreeParserCtxt:
7585 * @ctxt: the schema parser context
7586 *
7587 * Free the resources associated to the schema parser context
7588 */
7589void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007590xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
7591{
Daniel Veillard4255d502002-04-16 15:50:10 +00007592 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007593 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007594 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007595 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007596 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00007597 xmlFree(ctxt);
7598}
7599
7600/************************************************************************
7601 * *
7602 * Building the content models *
7603 * *
7604 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007605
Daniel Veillard4255d502002-04-16 15:50:10 +00007606/**
7607 * xmlSchemaBuildAContentModel:
7608 * @type: the schema type definition
7609 * @ctxt: the schema parser context
7610 * @name: the element name whose content is being built
7611 *
7612 * Generate the automata sequence needed for that type
7613 */
7614static void
7615xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007616 xmlSchemaParserCtxtPtr ctxt,
7617 const xmlChar * name)
7618{
Daniel Veillard4255d502002-04-16 15:50:10 +00007619 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007620 xmlGenericError(xmlGenericErrorContext,
7621 "Found unexpected type = NULL in %s content model\n",
7622 name);
7623 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007624 }
7625 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 case XML_SCHEMA_TYPE_ANY: {
7627 xmlAutomataStatePtr start, end;
7628 xmlSchemaWildcardPtr wild;
7629 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00007630
Daniel Veillardc0826a72004-08-10 14:17:33 +00007631 wild = type->attributeWildcard;
7632
7633 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007634 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635 "Internal error: xmlSchemaBuildAContentModel, "
7636 "no wildcard on xsd:any.\n", NULL, NULL);
7637 return;
7638 }
7639
7640 start = ctxt->state;
7641 end = xmlAutomataNewState(ctxt->am);
7642
7643 if (type->maxOccurs == 1) {
7644 if (wild->any == 1) {
7645 /*
7646 * We need to add both transitions:
7647 *
7648 * 1. the {"*", "*"} for elements in a namespace.
7649 */
7650 ctxt->state =
7651 xmlAutomataNewTransition2(ctxt->am,
7652 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7653 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7654 /*
7655 * 2. the {"*"} for elements in no namespace.
7656 */
7657 ctxt->state =
7658 xmlAutomataNewTransition2(ctxt->am,
7659 start, NULL, BAD_CAST "*", NULL, type);
7660 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7661
7662 } else if (wild->nsSet != NULL) {
7663 ns = wild->nsSet;
7664 do {
7665 ctxt->state = start;
7666 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7667 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
7668 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7669 ns = ns->next;
7670 } while (ns != NULL);
7671
7672 } else if (wild->negNsSet != NULL) {
7673 xmlAutomataStatePtr deadEnd;
7674
7675 deadEnd = xmlAutomataNewState(ctxt->am);
7676 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7677 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7678 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7679 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7680 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7681 }
7682 } else {
7683 int counter;
7684 xmlAutomataStatePtr hop;
7685 int maxOccurs =
7686 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
7687 int minOccurs =
7688 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
7689
7690 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
7691 hop = xmlAutomataNewState(ctxt->am);
7692 if (wild->any == 1) {
7693 ctxt->state =
7694 xmlAutomataNewTransition2(ctxt->am,
7695 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7696 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7697 ctxt->state =
7698 xmlAutomataNewTransition2(ctxt->am,
7699 start, NULL, BAD_CAST "*", NULL, type);
7700 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7701 } else if (wild->nsSet != NULL) {
7702 ns = wild->nsSet;
7703 do {
7704 ctxt->state =
7705 xmlAutomataNewTransition2(ctxt->am,
7706 start, NULL, BAD_CAST "*", ns->value, type);
7707 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7708 ns = ns->next;
7709 } while (ns != NULL);
7710
7711 } else if (wild->negNsSet != NULL) {
7712 xmlAutomataStatePtr deadEnd;
7713
7714 deadEnd = xmlAutomataNewState(ctxt->am);
7715 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7716 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7717 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7718 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7719 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7720 }
7721 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
7722 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
7723 }
7724 if (type->minOccurs == 0) {
7725 xmlAutomataNewEpsilon(ctxt->am, start, end);
7726 }
7727 ctxt->state = end;
7728 break;
7729 }
7730 case XML_SCHEMA_TYPE_ELEMENT:{
7731 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
7732
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007733 /* TODO : handle the namespace too */
7734 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007735
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007736 if (elem->maxOccurs >= UNBOUNDED) {
7737 if (elem->minOccurs > 1) {
7738 xmlAutomataStatePtr tmp;
7739 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007740
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007741 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7742 oldstate,
7743 NULL);
7744 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007745
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007746 counter = xmlAutomataNewCounter(ctxt->am,
7747 elem->minOccurs -
7748 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00007749
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007750 if (elem->refDecl != NULL) {
7751 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7752 elem->refDecl,
7753 ctxt,
7754 elem->refDecl->
7755 name);
7756 } else {
7757 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007758 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007759 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007760 elem->name,
7761 elem->targetNamespace,
7762 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007763 }
7764 tmp = ctxt->state;
7765 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7766 counter);
7767 ctxt->state =
7768 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7769 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00007770
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007771 } else {
7772 if (elem->refDecl != NULL) {
7773 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7774 elem->refDecl,
7775 ctxt,
7776 elem->refDecl->
7777 name);
7778 } else {
7779 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007780 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007781 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007782 elem->name,
7783 elem->targetNamespace,
7784 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007785 }
7786 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7787 oldstate);
7788 if (elem->minOccurs == 0) {
7789 /* basically an elem* */
7790 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7791 ctxt->state);
7792 }
7793 }
7794 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
7795 xmlAutomataStatePtr tmp;
7796 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007798 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7799 oldstate, NULL);
7800 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007801
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007802 counter = xmlAutomataNewCounter(ctxt->am,
7803 elem->minOccurs - 1,
7804 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007806 if (elem->refDecl != NULL) {
7807 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7808 elem->refDecl, ctxt,
7809 elem->refDecl->name);
7810 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007811 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007812 ctxt->state,
7813 NULL,
7814 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007815 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007816 type);
7817 }
7818 tmp = ctxt->state;
7819 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7820 counter);
7821 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
7822 NULL,
7823 counter);
7824 if (elem->minOccurs == 0) {
7825 /* basically an elem? */
7826 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7827 ctxt->state);
7828 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00007829
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007830 } else {
7831 if (elem->refDecl != NULL) {
7832 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7833 elem->refDecl, ctxt,
7834 elem->refDecl->name);
7835 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007836 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007837 ctxt->state,
7838 NULL,
7839 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007840 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007841 type);
7842 }
7843 if (elem->minOccurs == 0) {
7844 /* basically an elem? */
7845 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7846 ctxt->state);
7847 }
7848 }
7849 break;
7850 }
7851 case XML_SCHEMA_TYPE_SEQUENCE:{
7852 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007853
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007854 /*
7855 * If max and min occurances are default (1) then
7856 * simply iterate over the subtypes
7857 */
7858 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
7859 subtypes = type->subtypes;
7860 while (subtypes != NULL) {
7861 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7862 subtypes = subtypes->next;
7863 }
7864 } else {
7865 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007866
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007867 if (type->maxOccurs >= UNBOUNDED) {
7868 if (type->minOccurs > 1) {
7869 xmlAutomataStatePtr tmp;
7870 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007871
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007872 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7873 oldstate,
7874 NULL);
7875 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007876
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007877 counter = xmlAutomataNewCounter(ctxt->am,
7878 type->
7879 minOccurs - 1,
7880 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007881
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007882 subtypes = type->subtypes;
7883 while (subtypes != NULL) {
7884 xmlSchemaBuildAContentModel(subtypes, ctxt,
7885 name);
7886 subtypes = subtypes->next;
7887 }
7888 tmp = ctxt->state;
7889 xmlAutomataNewCountedTrans(ctxt->am, tmp,
7890 oldstate, counter);
7891 ctxt->state =
7892 xmlAutomataNewCounterTrans(ctxt->am, tmp,
7893 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007894
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007895 } else {
7896 subtypes = type->subtypes;
7897 while (subtypes != NULL) {
7898 xmlSchemaBuildAContentModel(subtypes, ctxt,
7899 name);
7900 subtypes = subtypes->next;
7901 }
7902 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7903 oldstate);
7904 if (type->minOccurs == 0) {
7905 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7906 ctxt->state);
7907 }
7908 }
7909 } else if ((type->maxOccurs > 1)
7910 || (type->minOccurs > 1)) {
7911 xmlAutomataStatePtr tmp;
7912 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007914 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7915 oldstate,
7916 NULL);
7917 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00007918
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007919 counter = xmlAutomataNewCounter(ctxt->am,
7920 type->minOccurs -
7921 1,
7922 type->maxOccurs -
7923 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007924
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007925 subtypes = type->subtypes;
7926 while (subtypes != NULL) {
7927 xmlSchemaBuildAContentModel(subtypes, ctxt,
7928 name);
7929 subtypes = subtypes->next;
7930 }
7931 tmp = ctxt->state;
7932 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7933 counter);
7934 ctxt->state =
7935 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7936 counter);
7937 if (type->minOccurs == 0) {
7938 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7939 ctxt->state);
7940 }
Daniel Veillardb509f152002-04-17 16:28:10 +00007941
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 } else {
7943 subtypes = type->subtypes;
7944 while (subtypes != NULL) {
7945 xmlSchemaBuildAContentModel(subtypes, ctxt,
7946 name);
7947 subtypes = subtypes->next;
7948 }
7949 if (type->minOccurs == 0) {
7950 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7951 ctxt->state);
7952 }
7953 }
7954 }
7955 break;
7956 }
7957 case XML_SCHEMA_TYPE_CHOICE:{
7958 xmlSchemaTypePtr subtypes;
7959 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00007960
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007961 start = ctxt->state;
7962 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00007963
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007964 /*
7965 * iterate over the subtypes and remerge the end with an
7966 * epsilon transition
7967 */
7968 if (type->maxOccurs == 1) {
7969 subtypes = type->subtypes;
7970 while (subtypes != NULL) {
7971 ctxt->state = start;
7972 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7973 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7974 subtypes = subtypes->next;
7975 }
7976 } else {
7977 int counter;
7978 xmlAutomataStatePtr hop;
7979 int maxOccurs = type->maxOccurs == UNBOUNDED ?
7980 UNBOUNDED : type->maxOccurs - 1;
7981 int minOccurs =
7982 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00007983
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007984 /*
7985 * use a counter to keep track of the number of transtions
7986 * which went through the choice.
7987 */
7988 counter =
7989 xmlAutomataNewCounter(ctxt->am, minOccurs,
7990 maxOccurs);
7991 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00007992
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007993 subtypes = type->subtypes;
7994 while (subtypes != NULL) {
7995 ctxt->state = start;
7996 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7997 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7998 subtypes = subtypes->next;
7999 }
8000 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8001 counter);
8002 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8003 counter);
8004 }
8005 if (type->minOccurs == 0) {
8006 xmlAutomataNewEpsilon(ctxt->am, start, end);
8007 }
8008 ctxt->state = end;
8009 break;
8010 }
8011 case XML_SCHEMA_TYPE_ALL:{
8012 xmlAutomataStatePtr start;
8013 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008014
Daniel Veillard3646d642004-06-02 19:19:14 +00008015 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008016 int lax;
8017
8018 subtypes = type->subtypes;
8019 if (subtypes == NULL)
8020 break;
8021 start = ctxt->state;
8022 while (subtypes != NULL) {
8023 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008024 /*
8025 * the following 'if' was needed to fix bug 139897
8026 * not quite sure why it only needs to be done for
8027 * elements with a 'ref', but it seems to work ok.
8028 */
8029 if (subtypes->ref != NULL)
8030 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00008031 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008032 /* TODO : handle the namespace too */
8033 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
8034 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
8035 ctxt->state, elem->name, 1,
8036 1, subtypes);
8037 } else {
8038 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
8039 ctxt->state, elem->name,
8040 elem->minOccurs,
8041 elem->maxOccurs,
8042 subtypes);
8043 }
8044 subtypes = subtypes->next;
8045 }
8046 lax = type->minOccurs == 0;
8047 ctxt->state =
8048 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8049 lax);
8050 break;
8051 }
8052 case XML_SCHEMA_TYPE_RESTRICTION:
8053 if (type->subtypes != NULL)
8054 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8055 break;
8056 case XML_SCHEMA_TYPE_EXTENSION:
8057 if (type->baseType != NULL) {
8058 xmlSchemaTypePtr subtypes;
8059
Daniel Veillardf7627552004-04-22 07:15:40 +00008060 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 /* TODO: Change the error code. */
8062 xmlSchemaPCustomErr(ctxt,
8063 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8064 NULL, type, type->node,
8065 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008066 return;
8067 }
8068 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008069 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008070 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008071 subtypes = type->subtypes;
8072 while (subtypes != NULL) {
8073 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8074 subtypes = subtypes->next;
8075 }
8076 } else if (type->subtypes != NULL)
8077 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8078 break;
8079 case XML_SCHEMA_TYPE_GROUP:
8080 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00008081 xmlSchemaTypePtr rgroup;
8082 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008083 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00008084 type->refNs);
8085 if (rgroup == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008086 xmlSchemaPResCompAttrErr(ctxt,
8087 XML_SCHEMAP_SRC_RESOLVE,
8088 NULL, type, NULL,
8089 "ref", type->ref, type->refNs,
8090 XML_SCHEMA_TYPE_GROUP, NULL);
William M. Brack29aa7722004-05-12 00:27:56 +00008091 return;
8092 }
8093 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
8094 break;
8095 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008096 }
8097 case XML_SCHEMA_TYPE_COMPLEX:
8098 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8099 if (type->subtypes != NULL)
8100 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8101 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008102 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8103 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008104 default:
8105 xmlGenericError(xmlGenericErrorContext,
8106 "Found unexpected type %d in %s content model\n",
8107 type->type, name);
8108 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008109 }
8110}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008111
Daniel Veillard4255d502002-04-16 15:50:10 +00008112/**
8113 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008114 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00008115 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008116 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008117 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008118 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00008119 */
8120static void
8121xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008122 xmlSchemaParserCtxtPtr ctxt,
8123 const xmlChar * name)
8124{
Daniel Veillard4255d502002-04-16 15:50:10 +00008125 xmlAutomataStatePtr start;
8126
Daniel Veillard4255d502002-04-16 15:50:10 +00008127 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008128 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008129 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008130 elem->contentType = XML_SCHEMA_CONTENT_ANY;
8131 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008132 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008133 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008134 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008135 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8136 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008137 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008138
8139#ifdef DEBUG_CONTENT
8140 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008141 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008142#endif
8143
Daniel Veillard4255d502002-04-16 15:50:10 +00008144 ctxt->am = xmlNewAutomata();
8145 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008146 xmlGenericError(xmlGenericErrorContext,
8147 "Cannot create automata for elem %s\n", name);
8148 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008149 }
8150 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
8151 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
8152 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00008153 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008154 if (elem->contModel == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008155 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 NULL, (xmlSchemaTypePtr) elem, NULL,
8157 "Failed to compile the content model", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008158 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008159 xmlSchemaPCustomErr(ctxt,
8160 XML_SCHEMAP_NOT_DETERMINISTIC,
8161 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008162 NULL, (xmlSchemaTypePtr) elem, NULL,
8163 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008164 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008165#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008166 xmlGenericError(xmlGenericErrorContext,
8167 "Content model of %s:\n", name);
8168 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008169#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008170 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008171 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008172 xmlFreeAutomata(ctxt->am);
8173 ctxt->am = NULL;
8174}
8175
8176/**
8177 * xmlSchemaRefFixupCallback:
8178 * @elem: the schema element context
8179 * @ctxt: the schema parser context
8180 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008181 * Resolves the references of an element declaration
8182 * or particle, which has an element declaration as it's
8183 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008184 */
8185static void
8186xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008187 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008188 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008189 const xmlChar * context ATTRIBUTE_UNUSED,
8190 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008191{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008192 if ((ctxt == NULL) || (elem == NULL) ||
8193 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008194 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008195 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008197 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008198
Daniel Veillardc0826a72004-08-10 14:17:33 +00008199 /*
8200 * TODO: Evaluate, what errors could occur if the declaration is not
8201 * found. It might be possible that the "typefixup" might crash if
8202 * no ref declaration was found.
8203 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008204 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008205 if (elemDecl == NULL) {
8206 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008207 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008208 NULL, (xmlSchemaTypePtr) elem, elem->node,
8209 "ref", elem->ref, elem->refNs,
8210 XML_SCHEMA_TYPE_ELEMENT, NULL);
8211 } else
8212 elem->refDecl = elemDecl;
8213 } else {
8214 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8215 xmlSchemaTypePtr type;
8216
8217 /* (type definition) ... otherwise the type definition ·resolved·
8218 * to by the ·actual value· of the type [attribute] ...
8219 */
8220 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8221 elem->namedTypeNs);
8222 if (type == NULL) {
8223 xmlSchemaPResCompAttrErr(ctxt,
8224 XML_SCHEMAP_SRC_RESOLVE,
8225 NULL, (xmlSchemaTypePtr) elem, elem->node,
8226 "type", elem->namedType, elem->namedTypeNs,
8227 XML_SCHEMA_TYPE_BASIC, "type definition");
8228 } else
8229 elem->subtypes = type;
8230 }
8231 if (elem->substGroup != NULL) {
8232 xmlSchemaElementPtr substHead;
8233
8234 /*
8235 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8236 * substitutionGroup?
8237 */
8238 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008239 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008240 if (substHead == NULL) {
8241 xmlSchemaPResCompAttrErr(ctxt,
8242 XML_SCHEMAP_SRC_RESOLVE,
8243 NULL, (xmlSchemaTypePtr) elem, NULL,
8244 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8245 XML_SCHEMA_TYPE_ELEMENT, NULL);
8246 } else {
8247 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8248 /*
8249 * (type definition)...otherwise the {type definition} of the
8250 * element declaration ·resolved· to by the ·actual value· of
8251 * the substitutionGroup [attribute], if present
8252 */
8253 if (elem->subtypes == NULL)
8254 elem->subtypes = substHead->subtypes;
8255 }
8256 }
8257 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8258 (elem->substGroup == NULL))
8259 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8260 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008261}
8262
William M. Bracke7091952004-05-11 15:09:58 +00008263/**
8264 * xmlSchemaParseListRefFixup:
8265 * @type: the schema type definition
8266 * @ctxt: the schema parser context
8267 *
8268 * Fixup of the itemType reference of the list type.
8269 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008270static void
William M. Bracke7091952004-05-11 15:09:58 +00008271xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008272{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008273
Daniel Veillard01fa6152004-06-29 17:04:39 +00008274 if (((type->base == NULL) &&
8275 (type->subtypes == NULL)) ||
8276 ((type->base != NULL) &&
8277 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008278 /*
8279 * src-list-itemType-or-simpleType
8280 * Either the itemType [attribute] or the <simpleType> [child] of
8281 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008282 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008283 /*
8284 * TODO: Move this to the parse function.
8285 */
8286 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008287 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008288 NULL, type, type->node,
8289 "The attribute 'itemType' and the <simpleType> child "
8290 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008291 } else if (type->base!= NULL) {
8292 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
8293 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008294 xmlSchemaPResCompAttrErr(ctxt,
8295 XML_SCHEMAP_SRC_RESOLVE,
8296 NULL, type, type->node,
8297 "itemType", type->base, type->baseNs,
8298 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008299 }
8300 }
8301 if ((type->subtypes != NULL) &&
8302 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8303 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008304}
8305
8306/**
8307 * xmlSchemaParseUnionRefCheck:
8308 * @typeDecl: the schema type definition
8309 * @ctxt: the schema parser context
8310 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00008311 * Checks and builds the memberTypes of the union type.
8312 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00008313 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008314static int
William M. Bracke7091952004-05-11 15:09:58 +00008315xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00008316 xmlSchemaParserCtxtPtr ctxt)
8317{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008318
Daniel Veillard01fa6152004-06-29 17:04:39 +00008319 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
8320 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00008321
Daniel Veillard01fa6152004-06-29 17:04:39 +00008322 /* 1 If the <union> alternative is chosen, then [Definition:]
8323 * define the explicit members as the type definitions ·resolved·
8324 * to by the items in the ·actual value· of the memberTypes [attribute],
8325 * if any, followed by the type definitions corresponding to the
8326 * <simpleType>s among the [children] of <union>, if any.
8327 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008328
Daniel Veillard01fa6152004-06-29 17:04:39 +00008329 if (type->type != XML_SCHEMA_TYPE_UNION)
8330 return (-1);
8331 if (ctxt->ctxtType == NULL) {
8332 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008333 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008334 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
8335 "available", NULL, NULL);
8336 return (-1);
8337 }
8338 /*
8339 * src-union-memberTypes-or-simpleTypes
8340 * Either the memberTypes [attribute] of the <union> element must
8341 * be non-empty or there must be at least one simpleType [child].
8342 */
8343 if ((type->base == NULL) &&
8344 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008345 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008346 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008347 NULL, NULL, type->node,
8348 "Either the attribute 'memberTypes' must be non-empty "
8349 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008350 }
8351
8352 ctxtType = ctxt->ctxtType;
8353 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008354 xmlAttrPtr attr;
8355 const xmlChar *cur, *end;
8356 xmlChar *tmp;
8357 const xmlChar *localName, *uri;
8358
8359 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00008360 cur = type->base;
8361 do {
8362 while (IS_BLANK_CH(*cur))
8363 cur++;
8364 end = cur;
8365 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8366 end++;
8367 if (end == cur)
8368 break;
8369 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008370 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
8371 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
8372 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008373 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008374 xmlSchemaPResCompAttrErr(ctxt,
8375 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
8376 NULL, NULL, type->node, "memberTypes", localName, uri,
8377 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008378 } else {
8379 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8380 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8381 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8382 if (link == NULL) {
8383 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8384 return (-1);
8385 }
8386 link->type = memberType;
8387 link->next = NULL;
8388 if (lastLink == NULL)
8389 ctxtType->memberTypes = link;
8390 else
8391 lastLink->next = link;
8392 lastLink = link;
8393 }
8394 xmlFree(tmp);
8395 cur = end;
8396 } while (*cur != 0);
8397 }
8398 /*
8399 * Add local simple types,
8400 */
8401 memberType = type->subtypes;
8402 while (memberType != NULL) {
8403 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8404 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8405 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8406 if (link == NULL) {
8407 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8408 return (-1);
8409 }
8410 link->type = memberType;
8411 link->next = NULL;
8412 if (lastLink == NULL)
8413 ctxtType->memberTypes = link;
8414 else
8415 lastLink->next = link;
8416 lastLink = link;
8417 memberType = memberType->next;
8418 }
8419 /*
8420 * The actual value is then formed by replacing any union type
8421 * definition in the ·explicit members· with the members of their
8422 * {member type definitions}, in order.
8423 */
8424 link = ctxtType->memberTypes;
8425 while (link != NULL) {
8426 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
8427 subLink = link->type->memberTypes;
8428 if (subLink != NULL) {
8429 link->type = subLink->type;
8430 if (subLink->next != NULL) {
8431 lastLink = link->next;
8432 subLink = subLink->next;
8433 prevLink = link;
8434 while (subLink != NULL) {
8435 newLink = (xmlSchemaTypeLinkPtr)
8436 xmlMalloc(sizeof(xmlSchemaTypeLink));
8437 if (newLink == NULL) {
8438 xmlSchemaPErrMemory(ctxt, "allocating a type link",
8439 NULL);
8440 return (-1);
8441 }
8442 newLink->type = memberType;
8443 prevLink->next = newLink;
8444 prevLink = newLink;
8445 newLink->next = lastLink;
8446
8447 subLink = subLink->next;
8448 }
8449 }
8450 }
8451 }
8452 link = link->next;
8453 }
8454
8455 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00008456}
8457
Daniel Veillard4255d502002-04-16 15:50:10 +00008458/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008459 * xmlSchemaIsDerivedFromBuiltInType:
8460 * @ctxt: the schema parser context
8461 * @type: the type definition
8462 * @valType: the value type
8463 *
8464 *
8465 * Returns 1 if the type has the given value type, or
8466 * is derived from such a type.
8467 */
William M. Brack803812b2004-06-03 02:11:24 +00008468static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008469xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
8470 xmlSchemaTypePtr type, int valType)
8471{
8472 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008473 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00008474 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008475 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00008476 return(1);
8477 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
8478 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
8479 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
8480 ((xmlSchemaAttributePtr) type)->subtypes, valType));
8481 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
8482 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
8483 if (type->baseType != NULL)
8484 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
8485 valType));
8486 } else if ((type->subtypes != NULL) &&
8487 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
8488 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
8489 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
8490 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
8491 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
8492 valType));
8493 }
8494
8495 return (0);
8496}
8497
8498/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00008499 * xmlSchemaIsDerivedFromBuiltInType:
8500 * @type: the simpleType definition
8501 *
8502 * Returns the primitive type of the given type or
8503 * NULL in case of error.
8504 */
8505static xmlSchemaTypePtr
8506xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
8507{
8508 while (type != NULL) {
8509 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
8510 return (type);
8511 type = type->baseType;
8512 }
8513
8514 return (NULL);
8515}
8516
8517
8518/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008519 * xmlSchemaBuildAttributeUsesOwned:
8520 * @ctxt: the schema parser context
8521 * @type: the complex type definition
8522 * @cur: the attribute declaration list
8523 * @lastUse: the top of the attribute use list
8524 *
8525 * Builds the attribute uses list on the given complex type.
8526 * This one is supposed to be called by
8527 * xmlSchemaBuildAttributeValidation only.
8528 */
8529static int
8530xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
8531 xmlSchemaAttributePtr cur,
8532 xmlSchemaAttributeLinkPtr *uses,
8533 xmlSchemaAttributeLinkPtr *lastUse)
8534{
8535 xmlSchemaAttributeLinkPtr tmp;
8536 while (cur != NULL) {
8537 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
8538 /*
8539 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
8540 * to by the ·actual value·s of the ref [attribute] of the
8541 * <attributeGroup> [children], if any."
8542 */
8543 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
8544 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
8545 lastUse) == -1) {
8546 return (-1);
8547 }
8548 } else {
8549 /* W3C: "1 The set of attribute uses corresponding to the
8550 * <attribute> [children], if any."
8551 */
8552 tmp = (xmlSchemaAttributeLinkPtr)
8553 xmlMalloc(sizeof(xmlSchemaAttributeLink));
8554 if (tmp == NULL) {
8555 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
8556 return (-1);
8557 }
8558 tmp->attr = cur;
8559 tmp->next = NULL;
8560 if (*uses == NULL)
8561 *uses = tmp;
8562 else
8563 (*lastUse)->next = tmp;
8564 *lastUse = tmp;
8565 }
8566 cur = cur->next;
8567 }
8568 return (0);
8569}
8570
Daniel Veillard50355f02004-06-08 17:52:16 +00008571/**
8572 * xmlSchemaCloneWildcardNsConstraints:
8573 * @ctxt: the schema parser context
8574 * @dest: the destination wildcard
8575 * @source: the source wildcard
8576 *
8577 * Clones the namespace constraints of source
8578 * and assignes them to dest.
8579 * Returns -1 on internal error, 0 otherwise.
8580 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008581static int
8582xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
8583 xmlSchemaWildcardPtr *dest,
8584 xmlSchemaWildcardPtr source)
8585{
8586 xmlSchemaWildcardNsPtr cur, tmp, last;
8587
8588 if ((source == NULL) || (*dest == NULL))
8589 return(-1);
8590 (*dest)->any = source->any;
8591 cur = source->nsSet;
8592 last = NULL;
8593 while (cur != NULL) {
8594 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8595 if (tmp == NULL)
8596 return(-1);
8597 tmp->value = cur->value;
8598 if (last == NULL)
8599 (*dest)->nsSet = tmp;
8600 else
8601 last->next = tmp;
8602 last = tmp;
8603 cur = cur->next;
8604 }
8605 if ((*dest)->negNsSet != NULL)
8606 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
8607 if (source->negNsSet != NULL) {
8608 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8609 if ((*dest)->negNsSet == NULL)
8610 return(-1);
8611 (*dest)->negNsSet->value = source->negNsSet->value;
8612 } else
8613 (*dest)->negNsSet = NULL;
8614 return(0);
8615}
8616
Daniel Veillard50355f02004-06-08 17:52:16 +00008617/**
8618 * xmlSchemaUnionWildcards:
8619 * @ctxt: the schema parser context
8620 * @completeWild: the first wildcard
8621 * @curWild: the second wildcard
8622 *
8623 * Unions the namespace constraints of the given wildcards.
8624 * @completeWild will hold the resulting union.
8625 * Returns a positive error code on failure, -1 in case of an
8626 * internal error, 0 otherwise.
8627 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008628static int
8629xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
8630 xmlSchemaWildcardPtr completeWild,
8631 xmlSchemaWildcardPtr curWild)
8632{
8633 xmlSchemaWildcardNsPtr cur, curB, tmp;
8634
8635 /*
8636 * 1 If O1 and O2 are the same value, then that value must be the
8637 * value.
8638 */
8639 if ((completeWild->any == curWild->any) &&
8640 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8641 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8642
8643 if ((completeWild->negNsSet == NULL) ||
8644 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8645
8646 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008647 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008648
8649 /*
8650 * Check equality of sets.
8651 */
8652 cur = completeWild->nsSet;
8653 while (cur != NULL) {
8654 found = 0;
8655 curB = curWild->nsSet;
8656 while (curB != NULL) {
8657 if (cur->value == curB->value) {
8658 found = 1;
8659 break;
8660 }
8661 curB = curB->next;
8662 }
8663 if (!found)
8664 break;
8665 cur = cur->next;
8666 }
8667 if (found)
8668 return(0);
8669 } else
8670 return(0);
8671 }
8672 }
8673 /*
8674 * 2 If either O1 or O2 is any, then any must be the value
8675 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008676 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008677 if (completeWild->any == 0) {
8678 completeWild->any = 1;
8679 if (completeWild->nsSet != NULL) {
8680 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8681 completeWild->nsSet = NULL;
8682 }
8683 if (completeWild->negNsSet != NULL) {
8684 xmlFree(completeWild->negNsSet);
8685 completeWild->negNsSet = NULL;
8686 }
8687 }
Daniel Veillard50355f02004-06-08 17:52:16 +00008688 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008689 }
8690 /*
8691 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
8692 * then the union of those sets must be the value.
8693 */
8694 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8695 int found;
8696 xmlSchemaWildcardNsPtr start;
8697
8698 cur = curWild->nsSet;
8699 start = completeWild->nsSet;
8700 while (cur != NULL) {
8701 found = 0;
8702 curB = start;
8703 while (curB != NULL) {
8704 if (cur->value == curB->value) {
8705 found = 1;
8706 break;
8707 }
8708 curB = curB->next;
8709 }
8710 if (!found) {
8711 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8712 if (tmp == NULL)
8713 return (-1);
8714 tmp->value = cur->value;
8715 tmp->next = completeWild->nsSet;
8716 completeWild->nsSet = tmp;
8717 }
8718 cur = cur->next;
8719 }
8720
8721 return(0);
8722 }
8723 /*
8724 * 4 If the two are negations of different values (namespace names
8725 * or ·absent·), then a pair of not and ·absent· must be the value.
8726 */
8727 if ((completeWild->negNsSet != NULL) &&
8728 (curWild->negNsSet != NULL) &&
8729 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
8730 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00008731
8732 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008733 }
8734 /*
8735 * 5.
8736 */
8737 if (((completeWild->negNsSet != NULL) &&
8738 (completeWild->negNsSet->value != NULL) &&
8739 (curWild->nsSet != NULL)) ||
8740 ((curWild->negNsSet != NULL) &&
8741 (curWild->negNsSet->value != NULL) &&
8742 (completeWild->nsSet != NULL))) {
8743
8744 int nsFound, absentFound = 0;
8745
8746 if (completeWild->nsSet != NULL) {
8747 cur = completeWild->nsSet;
8748 curB = curWild->negNsSet;
8749 } else {
8750 cur = curWild->nsSet;
8751 curB = completeWild->negNsSet;
8752 }
8753 nsFound = 0;
8754 while (cur != NULL) {
8755 if (cur->value == NULL)
8756 absentFound = 1;
8757 else if (cur->value == curB->value)
8758 nsFound = 1;
8759 if (nsFound && absentFound)
8760 break;
8761 cur = cur->next;
8762 }
8763
8764 if (nsFound && absentFound) {
8765 /*
8766 * 5.1 If the set S includes both the negated namespace
8767 * name and ·absent·, then any must be the value.
8768 */
8769 completeWild->any = 1;
8770 if (completeWild->nsSet != NULL) {
8771 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8772 completeWild->nsSet = NULL;
8773 }
8774 if (completeWild->negNsSet != NULL) {
8775 xmlFree(completeWild->negNsSet);
8776 completeWild->negNsSet = NULL;
8777 }
8778 } else if (nsFound && (!absentFound)) {
8779 /*
8780 * 5.2 If the set S includes the negated namespace name
8781 * but not ·absent·, then a pair of not and ·absent· must
8782 * be the value.
8783 */
8784 if (completeWild->nsSet != NULL) {
8785 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8786 completeWild->nsSet = NULL;
8787 }
8788 if (completeWild->negNsSet == NULL) {
8789 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8790 if (completeWild->negNsSet == NULL)
8791 return (-1);
8792 }
8793 completeWild->negNsSet->value = NULL;
8794 } else if ((!nsFound) && absentFound) {
8795 /*
8796 * 5.3 If the set S includes ·absent· but not the negated
8797 * namespace name, then the union is not expressible.
8798 */
8799 xmlSchemaPErr(ctxt, completeWild->node,
8800 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008801 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008802 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008803 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008804 } else if ((!nsFound) && (!absentFound)) {
8805 /*
8806 * 5.4 If the set S does not include either the negated namespace
8807 * name or ·absent·, then whichever of O1 or O2 is a pair of not
8808 * and a namespace name must be the value.
8809 */
8810 if (completeWild->negNsSet == NULL) {
8811 if (completeWild->nsSet != NULL) {
8812 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8813 completeWild->nsSet = NULL;
8814 }
8815 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8816 if (completeWild->negNsSet == NULL)
8817 return (-1);
8818 completeWild->negNsSet->value = curWild->negNsSet->value;
8819 }
8820 }
8821 return (0);
8822 }
8823 /*
8824 * 6.
8825 */
8826 if (((completeWild->negNsSet != NULL) &&
8827 (completeWild->negNsSet->value == NULL) &&
8828 (curWild->nsSet != NULL)) ||
8829 ((curWild->negNsSet != NULL) &&
8830 (curWild->negNsSet->value == NULL) &&
8831 (completeWild->nsSet != NULL))) {
8832
8833 if (completeWild->nsSet != NULL) {
8834 cur = completeWild->nsSet;
8835 } else {
8836 cur = curWild->nsSet;
8837 }
8838 while (cur != NULL) {
8839 if (cur->value == NULL) {
8840 /*
8841 * 6.1 If the set S includes ·absent·, then any must be the
8842 * value.
8843 */
8844 completeWild->any = 1;
8845 if (completeWild->nsSet != NULL) {
8846 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8847 completeWild->nsSet = NULL;
8848 }
8849 if (completeWild->negNsSet != NULL) {
8850 xmlFree(completeWild->negNsSet);
8851 completeWild->negNsSet = NULL;
8852 }
8853 return (0);
8854 }
8855 cur = cur->next;
8856 }
8857 if (completeWild->negNsSet == NULL) {
8858 /*
8859 * 6.2 If the set S does not include ·absent·, then a pair of not
8860 * and ·absent· must be the value.
8861 */
8862 if (completeWild->nsSet != NULL) {
8863 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8864 completeWild->nsSet = NULL;
8865 }
8866 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8867 if (completeWild->negNsSet == NULL)
8868 return (-1);
8869 completeWild->negNsSet->value = NULL;
8870 }
8871 return (0);
8872 }
8873 return (0);
8874
8875}
8876
Daniel Veillard50355f02004-06-08 17:52:16 +00008877/**
8878 * xmlSchemaIntersectWildcards:
8879 * @ctxt: the schema parser context
8880 * @completeWild: the first wildcard
8881 * @curWild: the second wildcard
8882 *
8883 * Intersects the namespace constraints of the given wildcards.
8884 * @completeWild will hold the resulting intersection.
8885 * Returns a positive error code on failure, -1 in case of an
8886 * internal error, 0 otherwise.
8887 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008888static int
8889xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
8890 xmlSchemaWildcardPtr completeWild,
8891 xmlSchemaWildcardPtr curWild)
8892{
William M. Brack803812b2004-06-03 02:11:24 +00008893 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008894
8895 /*
8896 * 1 If O1 and O2 are the same value, then that value must be the
8897 * value.
8898 */
8899 if ((completeWild->any == curWild->any) &&
8900 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8901 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8902
8903 if ((completeWild->negNsSet == NULL) ||
8904 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8905
8906 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008907 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008908
8909 /*
8910 * Check equality of sets.
8911 */
8912 cur = completeWild->nsSet;
8913 while (cur != NULL) {
8914 found = 0;
8915 curB = curWild->nsSet;
8916 while (curB != NULL) {
8917 if (cur->value == curB->value) {
8918 found = 1;
8919 break;
8920 }
8921 curB = curB->next;
8922 }
8923 if (!found)
8924 break;
8925 cur = cur->next;
8926 }
8927 if (found)
8928 return(0);
8929 } else
8930 return(0);
8931 }
8932 }
8933 /*
8934 * 2 If either O1 or O2 is any, then the other must be the value.
8935 */
8936 if ((completeWild->any != curWild->any) && (completeWild->any)) {
8937 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8938 return(-1);
8939 return(0);
8940 }
8941 /*
8942 * 3 If either O1 or O2 is a pair of not and a value (a namespace
8943 * name or ·absent·) and the other is a set of (namespace names or
8944 * ·absent·), then that set, minus the negated value if it was in
8945 * the set, minus ·absent· if it was in the set, must be the value.
8946 */
8947 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
8948 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
8949 const xmlChar *neg;
8950
8951 if (completeWild->nsSet == NULL) {
8952 neg = completeWild->negNsSet->value;
8953 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8954 return(-1);
8955 } else
8956 neg = curWild->negNsSet->value;
8957 /*
8958 * Remove absent and negated.
8959 */
8960 prev = NULL;
8961 cur = completeWild->nsSet;
8962 while (cur != NULL) {
8963 if (cur->value == NULL) {
8964 if (prev == NULL)
8965 completeWild->nsSet = cur->next;
8966 else
8967 prev->next = cur->next;
8968 xmlFree(cur);
8969 break;
8970 }
8971 prev = cur;
8972 cur = cur->next;
8973 }
8974 if (neg != NULL) {
8975 prev = NULL;
8976 cur = completeWild->nsSet;
8977 while (cur != NULL) {
8978 if (cur->value == neg) {
8979 if (prev == NULL)
8980 completeWild->nsSet = cur->next;
8981 else
8982 prev->next = cur->next;
8983 xmlFree(cur);
8984 break;
8985 }
8986 prev = cur;
8987 cur = cur->next;
8988 }
8989 }
8990
8991 return(0);
8992 }
8993 /*
8994 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
8995 * then the intersection of those sets must be the value.
8996 */
8997 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8998 int found;
8999
9000 cur = completeWild->nsSet;
9001 prev = NULL;
9002 while (cur != NULL) {
9003 found = 0;
9004 curB = curWild->nsSet;
9005 while (curB != NULL) {
9006 if (cur->value == curB->value) {
9007 found = 1;
9008 break;
9009 }
9010 curB = curB->next;
9011 }
9012 if (!found) {
9013 if (prev == NULL)
9014 completeWild->nsSet = cur->next;
9015 else
9016 prev->next = cur->next;
9017 tmp = cur->next;
9018 xmlFree(cur);
9019 cur = tmp;
9020 continue;
9021 }
9022 prev = cur;
9023 cur = cur->next;
9024 }
9025
9026 return(0);
9027 }
9028 /* 5 If the two are negations of different namespace names,
9029 * then the intersection is not expressible
9030 */
9031 if ((completeWild->negNsSet != NULL) &&
9032 (curWild->negNsSet != NULL) &&
9033 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9034 (completeWild->negNsSet->value != NULL) &&
9035 (curWild->negNsSet->value != NULL)) {
9036
9037 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009038 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009039 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009040 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009041 }
9042 /*
9043 * 6 If the one is a negation of a namespace name and the other
9044 * is a negation of ·absent·, then the one which is the negation
9045 * of a namespace name must be the value.
9046 */
9047 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9048 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9049 (completeWild->negNsSet->value == NULL)) {
9050 completeWild->negNsSet->value = curWild->negNsSet->value;
9051 }
9052 return(0);
9053}
9054
Daniel Veillard50355f02004-06-08 17:52:16 +00009055/**
9056 * xmlSchemaIsWildcardNsConstraintSubset:
9057 * @ctxt: the schema parser context
9058 * @wildA: the first wildcard
9059 * @wildB: the second wildcard
9060 *
9061 * Returns 1 if the namespace constraint of @wildA is an intensional
9062 * subset of @wildB, 0 otherwise.
9063 */
9064static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009065xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9066 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009067{
Daniel Veillard3646d642004-06-02 19:19:14 +00009068
Daniel Veillard50355f02004-06-08 17:52:16 +00009069 /*
9070 * Schema Component Constraint: Wildcard Subset
9071 */
9072 /*
9073 * 1 super must be any.
9074 */
9075 if (wildB->any)
9076 return (1);
9077 /*
9078 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9079 * 2.2 super must be a pair of not and the same value.
9080 */
9081 if ((wildA->negNsSet != NULL) &&
9082 (wildB->negNsSet != NULL) &&
9083 (wildA->negNsSet->value == wildA->negNsSet->value))
9084 return (1);
9085 /*
9086 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9087 */
9088 if (wildA->nsSet != NULL) {
9089 /*
9090 * 3.2.1 super must be the same set or a superset thereof.
9091 */
9092 if (wildB->nsSet != NULL) {
9093 xmlSchemaWildcardNsPtr cur, curB;
9094 int found = 0;
9095
9096 cur = wildA->nsSet;
9097 while (cur != NULL) {
9098 found = 0;
9099 curB = wildB->nsSet;
9100 while (curB != NULL) {
9101 if (cur->value == curB->value) {
9102 found = 1;
9103 break;
9104 }
9105 curB = curB->next;
9106 }
9107 if (!found)
9108 return (0);
9109 cur = cur->next;
9110 }
9111 if (found)
9112 return (1);
9113 } else if (wildB->negNsSet != NULL) {
9114 xmlSchemaWildcardNsPtr cur;
9115 /*
9116 * 3.2.2 super must be a pair of not and a namespace name or
9117 * ·absent· and that value must not be in sub's set.
9118 */
9119 cur = wildA->nsSet;
9120 while (cur != NULL) {
9121 if (cur->value == wildB->negNsSet->value)
9122 return (0);
9123 cur = cur->next;
9124 }
9125 return (1);
9126 }
9127 }
9128 return (0);
9129}
9130
9131/**
9132 * xmlSchemaBuildCompleteAttributeWildcard:
9133 * @ctxt: the schema parser context
9134 * @attrs: the attribute list
9135 * @completeWild: the resulting complete wildcard
9136 *
9137 * Returns -1 in case of an internal error, 0 otherwise.
9138 */
9139static int
9140xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9141 xmlSchemaAttributePtr attrs,
9142 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009143{
9144 while (attrs != NULL) {
9145 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9146 xmlSchemaAttributeGroupPtr group;
9147
9148 group = (xmlSchemaAttributeGroupPtr) attrs;
9149 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9150 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009151 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9152 group->attributes, &group->attributeWildcard) == -1)
9153 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009154 }
9155 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9156 }
9157 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009158 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009159 /*
9160 * Copy the first encountered wildcard as context, except for the annotation.
9161 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009162 *completeWild = xmlSchemaAddWildcard(ctxt);
9163 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9164 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9165 completeWild, group->attributeWildcard) == -1)
9166 return (-1);
9167 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009168 /*
9169 * Although the complete wildcard might not correspond to any
9170 * node in the schema, we will save this context node.
9171 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009172 (*completeWild)->node = group->attributeWildcard->node;
9173
9174 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9175 xmlSchemaFreeWildcard(*completeWild);
9176 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009177 }
9178 }
9179 }
9180 attrs = attrs->next;
9181 }
9182
Daniel Veillard50355f02004-06-08 17:52:16 +00009183 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009184}
9185
9186/**
9187 * xmlSchemaMatchesWildcardNs:
9188 * @wild: the wildcard
9189 * @ns: the namespace
9190 *
9191 *
9192 * Returns 1 if the given namespace matches the wildcard,
9193 * 0 otherwise.
9194 */
9195static int
9196xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9197{
9198 if (wild == NULL)
9199 return(0);
9200
9201 if (wild->any)
9202 return(1);
9203 else if (wild->nsSet != NULL) {
9204 xmlSchemaWildcardNsPtr cur;
9205
9206 cur = wild->nsSet;
9207 while (cur != NULL) {
9208 if (xmlStrEqual(cur->value, ns))
9209 return(1);
9210 cur = cur->next;
9211 }
9212 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9213 (!xmlStrEqual(wild->negNsSet->value, ns)))
9214 return(1);
9215
9216 return(0);
9217}
9218
9219/**
9220 * xmlSchemaBuildAttributeValidation:
9221 * @ctxt: the schema parser context
9222 * @type: the complex type definition
9223 *
9224 *
9225 * Builds the wildcard and the attribute uses on the given complex type.
9226 * Returns -1 if an internal error occurs, 0 otherwise.
9227 */
9228static int
9229xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
9230{
9231 xmlSchemaTypePtr baseType = NULL;
9232 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00009233 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009234 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009235 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00009236 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009237 xmlChar *str = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009238
Daniel Veillard01fa6152004-06-29 17:04:39 +00009239 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009240 /*
9241 * Complex Type Definition with complex content Schema Component.
9242 *
9243 * Attribute uses.
9244 */
9245 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009246 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009247 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00009248 "attribute uses already builded.\n",
9249 NULL, NULL);
9250 return (-1);
9251 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009252 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009253 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009254 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009255 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009256 type->name, NULL);
9257 return (-1);
9258 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009259 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009260 if (baseType == anyType)
9261 baseIsAnyType = 1;
9262 /*
9263 * Inherit the attribute uses of the base type.
9264 */
9265 /*
9266 * NOTE: It is allowed to "extend" the anyType complex type.
9267 */
9268 if (!baseIsAnyType) {
9269 if (baseType != NULL) {
9270 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
9271 tmp = (xmlSchemaAttributeLinkPtr)
9272 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9273 if (tmp == NULL) {
9274 xmlSchemaPErrMemory(ctxt,
9275 "building attribute uses of complexType", NULL);
9276 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009277 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009278 tmp->attr = cur->attr;
9279 tmp->next = NULL;
9280 if (type->attributeUses == NULL) {
9281 type->attributeUses = tmp;
9282 } else
9283 lastBaseUse->next = tmp;
9284 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009285 }
9286 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009287 }
9288 if ((type->subtypes != NULL) &&
9289 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9290 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9291 attrs = type->subtypes->subtypes->attributes;
9292 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
9293 } else {
9294 /* Short hand form of the complexType. */
9295 attrs = type->attributes;
9296 }
9297 /*
9298 * Handle attribute wildcards.
9299 */
9300 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9301 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009302 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009303 /* Either we used the short hand form... */
9304 ((type->subtypes == NULL) ||
9305 /* Or complexType -> restriction/extension */
9306 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00009307 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009308 return (-1);
9309 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009310 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009311 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
9312 * create the wildcard right from the start on the complexType,
9313 * rather than on the <restriction>/<extension>.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009314 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009315 if ((type->attributeWildcard != NULL) &&
9316 /* Either we used the short hand form... */
9317 ((type->subtypes == NULL) ||
9318 /* Or complexType -> restriction/extension */
9319 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
9320 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
9321
9322 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
9323 ((baseIsAnyType) ||
9324 ((baseType != NULL) &&
9325 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9326 (baseType->attributeWildcard != NULL)))) {
9327 if (type->attributeWildcard != NULL) {
9328 /*
9329 * Union the complete wildcard with the base wildcard.
9330 */
9331 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
9332 baseType->attributeWildcard) == -1)
9333 return (-1);
9334 } else {
9335 /*
9336 * Just inherit the wildcard.
9337 */
9338 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00009339 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009340 }
9341
9342 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9343 if (type->attributeWildcard != NULL) {
9344 /*
9345 * Derivation Valid (Restriction, Complex)
9346 * 4.1 The {base type definition} must also have one.
9347 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009348 if (baseType->attributeWildcard == NULL) {
9349 xmlSchemaPCustomErr(ctxt,
9350 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
9351 NULL, type, NULL,
9352 "The type has an attribute wildcard, "
9353 "but the base type %s does not have one",
9354 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9355 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009356 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009357 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009358 type->attributeWildcard, baseType->attributeWildcard) == 0) {
9359 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009360 xmlSchemaPCustomErr(ctxt,
9361 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
9362 NULL, type, NULL,
9363 "The attribute wildcard is not a valid "
9364 "subset of the wildcard in the base type %s",
9365 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9366 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009367 return (1);
9368 }
9369 /* 4.3 Unless the {base type definition} is the ·ur-type
9370 * definition·, the complex type definition's {attribute
9371 * wildcard}'s {process contents} must be identical to or
9372 * stronger than the {base type definition}'s {attribute
9373 * wildcard}'s {process contents}, where strict is stronger
9374 * than lax is stronger than skip.
9375 */
9376 if ((type->baseType != anyType) &&
9377 (type->attributeWildcard->processContents <
9378 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009379 xmlSchemaPCustomErr(ctxt,
9380 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
9381 NULL, type, NULL,
9382 "The 'process contents' of the attribute wildcard is weaker than "
9383 "the one in the base type %s",
9384 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9385 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009386 return (1);
9387 }
9388 }
9389 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9390 /*
9391 * Derivation Valid (Extension)
9392 * At this point the type and the base have both, either
9393 * no wildcard or a wildcard.
9394 */
9395 if ((baseType->attributeWildcard != NULL) &&
9396 (baseType->attributeWildcard != type->attributeWildcard)) {
9397 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009398 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009399 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009400 xmlSchemaPCustomErr(ctxt,
9401 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
9402 NULL, type, NULL,
9403 "The attribute wildcard is not a valid "
9404 "superset of the one in the base type %s",
9405 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9406 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009407 return (1);
9408 }
9409 }
9410 }
9411
Daniel Veillard3646d642004-06-02 19:19:14 +00009412 /*
9413 * Gather attribute uses defined by this type.
9414 */
9415 if (attrs != NULL) {
9416 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
9417 &uses, &lastUse) == -1) {
9418 return (-1);
9419 }
9420 }
9421 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
9422 * "Two distinct attribute declarations in the {attribute uses} must
9423 * not have identical {name}s and {target namespace}s."
9424 *
9425 * For "extension" this is done further down.
9426 */
9427 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
9428 cur = uses;
9429 while (cur != NULL) {
9430 tmp = cur->next;
9431 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009432 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9433 xmlSchemaGetAttrName(tmp->attr))) &&
9434 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9435 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
9436
9437 xmlSchemaPAttrUseErr(ctxt,
9438 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9439 NULL, type, NULL, cur->attr,
9440 "Duplicate attribute use %s specified",
9441 xmlSchemaFormatNsUriLocal(&str,
9442 xmlSchemaGetAttrTargetNsURI(tmp->attr),
9443 xmlSchemaGetAttrName(tmp->attr))
9444 );
9445 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009446 break;
9447 }
9448 tmp = tmp->next;
9449 }
9450 cur = cur->next;
9451 }
9452 }
9453 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9454 /*
9455 * Derive by restriction.
9456 */
9457 if (baseIsAnyType) {
9458 type->attributeUses = uses;
9459 } else {
9460 int found;
9461
9462 cur = uses;
9463 while (cur != NULL) {
9464 found = 0;
9465 base = type->attributeUses;
9466 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009467 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9468 xmlSchemaGetAttrName(base->attr)) &&
9469 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
9470 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009471
Daniel Veillardc0826a72004-08-10 14:17:33 +00009472 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009473 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
9474 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9475 /*
9476 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +00009477 */
9478 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00009479 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009480 NULL, type, NULL, cur->attr,
9481 "The 'optional' use is inconsistent with a matching "
9482 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009483 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
9484 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9485 /*
9486 * derivation-ok-restriction 3
9487 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009488 xmlSchemaPCustomErr(ctxt,
9489 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
9490 NULL, type, NULL,
9491 "A matching attribute use for the 'required' "
9492 "attribute use %s of the base type is missing",
9493 xmlSchemaFormatNsUriLocal(&str,
9494 xmlSchemaGetAttrTargetNsURI(base->attr),
9495 xmlSchemaGetAttrName(base->attr)));
9496 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009497 } else {
9498 /*
9499 * Override the attribute use.
9500 */
9501 base->attr = cur->attr;
9502 }
9503 /*
9504 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00009505 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00009506 */
9507 break;
9508 }
9509 base = base->next;
9510 }
9511
9512 if (!found) {
9513 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9514 /*
9515 * derivation-ok-restriction 2.2
9516 */
9517 if ((type->attributeWildcard != NULL) &&
9518 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
9519 cur->attr->targetNamespace))
9520 found = 1;
9521
9522 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009523 xmlSchemaPAttrUseErr(ctxt,
9524 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
9525 NULL, type, NULL, cur->attr,
9526 "Neither a matching attribute use, "
9527 "nor a matching wildcard in the base type does exist",
9528 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009529 } else {
9530 /*
9531 * Add the attribute use.
9532 *
9533 * Note that this may lead to funny derivation error reports, if
9534 * multiple equal attribute uses exist; but this is not
9535 * allowed anyway, and it will be reported beforehand.
9536 */
9537 tmp = cur;
9538 if (prev != NULL)
9539 prev->next = cur->next;
9540 else
9541 uses = cur->next;
9542 cur = cur->next;
9543 if (type->attributeUses == NULL) {
9544 type->attributeUses = tmp;
9545 } else
9546 lastBaseUse->next = tmp;
9547 lastBaseUse = tmp;
9548
9549 continue;
9550 }
9551 }
9552 }
9553 prev = cur;
9554 cur = cur->next;
9555 }
9556 if (uses != NULL)
9557 xmlSchemaFreeAttributeUseList(uses);
9558 }
9559 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9560 /*
9561 * The spec allows only appending, and not other kinds of extensions.
9562 *
9563 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
9564 */
9565 if (uses != NULL) {
9566 if (type->attributeUses == NULL) {
9567 type->attributeUses = uses;
9568 } else
9569 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009570 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009571 } else {
9572 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00009573 * Derive implicitely from the ur-type.
9574 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009575 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009576 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009577 /*
9578 * 3.4.6 -> Complex Type Definition Properties Correct
9579 */
9580 if (type->attributeUses != NULL) {
9581 cur = type->attributeUses;
9582 prev = NULL;
9583 while (cur != NULL) {
9584 /*
9585 * 4. Two distinct attribute declarations in the {attribute uses} must
9586 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00009587 *
Daniel Veillard3646d642004-06-02 19:19:14 +00009588 * Note that this was already done for "restriction" and types derived from
9589 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00009590 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009591 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9592 tmp = cur->next;
9593 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009594 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9595 xmlSchemaGetAttrName(tmp->attr))) &&
9596 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9597 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009598
Daniel Veillardc0826a72004-08-10 14:17:33 +00009599 xmlSchemaPAttrUseErr(ctxt,
9600 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9601 NULL, type, NULL, tmp->attr,
9602 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009603 break;
9604 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009605 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009606 }
9607 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009608 /*
9609 * 5. Two distinct attribute declarations in the {attribute uses} must
9610 * not have {type definition}s which are or are derived from ID.
9611 */
9612 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009613 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009614 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009615 xmlSchemaPAttrUseErr(ctxt,
9616 XML_SCHEMAP_CT_PROPS_CORRECT_5,
9617 NULL, type, NULL, cur->attr,
9618 "There must not exist more than one attribute use, "
9619 "declared of type 'ID' or derived from it",
9620 NULL);
9621 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +00009622 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009623 id = cur;
9624 }
9625 /*
9626 * Remove "prohibited" attribute uses. The reason this is done at this late
9627 * stage is to be able to catch dublicate attribute uses. So we had to keep
9628 * prohibited uses in the list as well.
9629 */
9630 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9631 tmp = cur;
9632 if (prev == NULL)
9633 type->attributeUses = cur->next;
9634 else
9635 prev->next = cur->next;
9636 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009637 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00009638 } else {
9639 prev = cur;
9640 cur = cur->next;
9641 }
9642 }
9643 }
9644 /*
9645 * TODO: This check should be removed if we are 100% sure of
9646 * the base type attribute uses already being built.
9647 */
9648 if ((baseType != NULL) && (!baseIsAnyType) &&
9649 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9650 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009651 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009652 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009653 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009654 baseType->name, NULL);
9655 }
9656 return (0);
9657}
9658
9659/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009660 * xmlSchemaTypeFinalContains:
9661 * @schema: the schema
9662 * @type: the type definition
9663 * @final: the final
9664 *
9665 * Evaluates if a type definition contains the given "final".
9666 * This does take "finalDefault" into account as well.
9667 *
9668 * Returns 1 if the type does containt the given "final",
9669 * 0 otherwise.
9670 */
9671static int
9672xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
9673{
9674 int tfinal = final, tflags = type->flags;
9675
9676 if (type == NULL)
9677 return (0);
9678 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
9679 switch (final) {
9680 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
9681 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9682 break;
9683 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
9684 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9685 break;
9686 case XML_SCHEMAS_TYPE_FINAL_LIST:
9687 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
9688 break;
9689 case XML_SCHEMAS_TYPE_FINAL_UNION:
9690 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
9691 break;
9692 }
9693 tflags = schema->flags;
9694 }
9695 if (tflags & tfinal)
9696 return (1);
9697 else
9698 return (0);
9699
9700}
9701
9702/**
9703 * xmlSchemaGetUnionSimpleTypeMemberTypes:
9704 * @type: the Union Simple Type
9705 *
9706 * Returns a list of member types of @type if existing,
9707 * returns NULL otherwise.
9708 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009709static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00009710xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
9711{
9712 while (type != NULL) {
9713 if (type->memberTypes != NULL)
9714 return (type->memberTypes);
9715 else
9716 type = type->baseType;
9717 }
9718 return (NULL);
9719}
9720
9721/**
9722 * xmlSchemaGetListSimpleTypeItemType:
9723 * @type: the simple type definition
9724 *
9725 * Returns the item type definition of the list simple type.
9726 */
9727static xmlSchemaTypePtr
9728xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
9729{
9730 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
9731 return (NULL);
9732 /*
9733 * Note: In libxml2, the built-in types do not reflect
9734 * the datatype hierarchy (yet?) - we have to treat them
9735 * in a special way.
9736 */
9737 if (type->type == XML_SCHEMA_TYPE_BASIC)
9738 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
9739 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
9740 /* 1 If the <list> alternative is chosen, then the type
9741 * definition ·resolved· to by the ·actual value· of the
9742 * itemType [attribute] of <list>, if present, otherwise
9743 * the type definition corresponding to the <simpleType>
9744 * among the [children] of <list>.
9745 */
9746 return (type->subtypes->subtypes);
9747 else {
9748 /* 2 If the <restriction> option is chosen, then the
9749 * {item type definition} of the {base type definition}.
9750 */
9751 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
9752 }
9753}
9754
9755/**
9756 * xmlSchemaCheckCOSSTDerivedOK:
9757 * @type: the derived simple type definition
9758 * @baseType: the base type definition
9759 *
9760 * Checks wheter @type can be validly
9761 * derived from @baseType.
9762 *
9763 * Returns 0 on success, an positive error code otherwise.
9764 */
9765static int
9766xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
9767 xmlSchemaTypePtr type,
9768 xmlSchemaTypePtr baseType,
9769 int subset)
9770{
9771 /*
9772 * Schema Component Constraint: Type Derivation OK (Simple)
9773 *
9774 *
9775 * 1 They are the same type definition.
9776 * TODO: The identy check might have to be more complex than this.
9777 */
9778 if (type == baseType)
9779 return (0);
9780 /*
9781 * 2.1 restriction is not in the subset, or in the {final}
9782 * of its own {base type definition};
9783 */
9784 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
9785 (xmlSchemaTypeFinalContains(schema,
9786 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
9787 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
9788 }
9789 /* 2.2 */
9790 if (type->baseType == baseType) {
9791 /*
9792 * 2.2.1 D's ·base type definition· is B.
9793 */
9794 return (0);
9795 }
9796 /*
9797 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
9798 * and is validly derived from B given the subset, as defined by this
9799 * constraint.
9800 */
9801 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
9802 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
9803 return (0);
9804 }
9805 /*
9806 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
9807 * definition·.
9808 */
9809 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
9810 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
9811 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
9812 return (0);
9813 }
9814 /*
9815 * 2.2.4 B's {variety} is union and D is validly derived from a type
9816 * definition in B's {member type definitions} given the subset, as
9817 * defined by this constraint.
9818 *
9819 * NOTE: This seems not to involve built-in types, since there is no
9820 * built-in Union Simple Type.
9821 */
9822 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9823 xmlSchemaTypeLinkPtr cur;
9824
9825 cur = baseType->memberTypes;
9826 while (cur != NULL) {
9827 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
9828 cur->type, subset) == 0)
9829 return (0);
9830 cur = cur->next;
9831 }
9832 }
9833
9834 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
9835}
9836
9837
9838/**
9839 * xmlSchemaCheckSTPropsCorrect:
9840 * @ctxt: the schema parser context
9841 * @type: the simple type definition
9842 *
9843 * Checks st-props-correct.
9844 *
9845 * Returns 0 if the properties are correct,
9846 * if not, a positive error code and -1 on internal
9847 * errors.
9848 */
9849static int
9850xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
9851 xmlSchemaTypePtr type)
9852{
9853 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
9854 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009855 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009856
Daniel Veillardc0826a72004-08-10 14:17:33 +00009857 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009858 /*
9859 * Schema Component Constraint: Simple Type Definition Properties Correct
9860 *
9861 * NOTE: This is somehow redundant, since we actually built a simple type
9862 * to have all the needed information; this acts as an self test.
9863 */
9864 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9865 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9866 /*
9867 * TODO: 1 The values of the properties of a simple type definition must be as
9868 * described in the property tableau in Datatype definition, modulo the
9869 * impact of Missing Sub-components (§5.3).
9870 */
9871 /* Base type: If the datatype has been ·derived· by ·restriction·
9872 * then the Simple Type Definition component from which it is ·derived·,
9873 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
9874 */
9875 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009876 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009877 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009878 NULL, type, NULL,
9879 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009880 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9881 }
9882 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
9883 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
9884 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009885 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009886 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009887 NULL, type, NULL,
9888 "The base type %s is not a simple type",
9889 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9890 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009891 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9892 }
9893 if ((baseType != anySimpleType) &&
9894 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009895 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009896 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009897 NULL, type, NULL,
9898 "A type, derived by list or union, must have"
9899 "the simple ur-type definition as base type, not %s",
9900 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9901 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009902 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9903 }
9904 /*
9905 * Variety: One of {atomic, list, union}.
9906 */
9907 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9908 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
9909 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009910 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009911 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009912 NULL, type, NULL,
9913 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009914 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9915 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009916 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009917
9918 /*
9919 * 2 All simple type definitions must be derived ultimately from the ·simple
9920 * ur-type definition (so· circular definitions are disallowed). That is, it
9921 * must be possible to reach a built-in primitive datatype or the ·simple
9922 * ur-type definition· by repeatedly following the {base type definition}.
9923 */
9924 baseType = type->baseType;
9925 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
9926 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9927 xmlSchemaTypeFixup(baseType, ctxt, NULL);
9928 if (baseType == anySimpleType)
9929 break;
9930 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009931 xmlSchemaPCustomErr(ctxt,
9932 XML_SCHEMAP_ST_PROPS_CORRECT_2,
9933 NULL, type, NULL,
9934 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009935 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
9936 }
9937 baseType = baseType->baseType;
9938 }
9939 /*
9940 * 3 The {final} of the {base type definition} must not contain restriction.
9941 */
9942 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
9943 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009944 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009945 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009946 NULL, type, NULL,
9947 "The 'final' of its base type %s must not contain "
9948 "'restriction'",
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_3);
9952 }
9953 return (0);
9954}
9955
9956/**
9957 * xmlSchemaCheckDerivationValidSimpleRestriction:
9958 * @ctxt: the schema parser context
9959 * @type: the simple type definition
9960 *
9961 * Checks if the given @type (simpleType) is derived
9962 * validly by restriction.
9963 *
9964 * Returns -1 on internal errors, 0 if the type is validly derived,
9965 * a positive error code otherwise.
9966 */
9967static int
9968xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009969 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009970{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009971 xmlChar *str = NULL;
9972
9973 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009974
9975 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
9976 xmlSchemaPErr(ctxt, type->node,
9977 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009978 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
9979 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009980 type->name, NULL);
9981 return (-1);
9982 }
9983
9984 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9985 xmlSchemaTypePtr primitive;
9986 /*
9987 * 1.1 The {base type definition} must be an atomic simple
9988 * type definition or a built-in primitive datatype.
9989 */
9990 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009991 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009992 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009993 NULL, type, NULL,
9994 "The base type %s is not an atomic simple type",
9995 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9996 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009997 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
9998 }
9999 /* 1.2 The {final} of the {base type definition} must not contain
10000 * restriction.
10001 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010002 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010003 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10004 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010005 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010006 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010007 NULL, type, NULL,
10008 "The final of its base type %s must not contain 'restriction'",
10009 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10010 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010011 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10012 }
10013
10014 /*
10015 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10016 * type definition}, as specified in the appropriate subsection of 3.2
10017 * Primitive datatypes.
10018 */
10019 if (type->facets != NULL) {
10020 xmlSchemaFacetPtr facet;
10021 int ok = 1;
10022
10023 primitive = xmlSchemaGetPrimitiveType(type);
10024 if (primitive == NULL) {
10025 xmlSchemaPErr(ctxt, type->node,
10026 XML_ERR_INTERNAL_ERROR,
10027 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010028 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010029 type->name, NULL);
10030 return (-1);
10031 }
10032 facet = type->facets;
10033 do {
10034 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010035 ok = 0;
10036 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010037 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010038 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010039 }
10040 facet = facet->next;
10041 } while (facet != NULL);
10042 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010043 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010044 }
10045 /*
10046 * TODO: 1.3.2 (facet derivation)
10047 */
10048 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10049 xmlSchemaTypePtr itemType = NULL;
10050
10051 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10052 if (itemType == NULL) {
10053 xmlSchemaPErr(ctxt, type->node,
10054 XML_ERR_INTERNAL_ERROR,
10055 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010056 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010057 type->name, NULL);
10058 return (-1);
10059 }
10060 /*
10061 * 2.1 The {item type definition} must have a {variety} of atomic or
10062 * union (in which case all the {member type definitions}
10063 * must be atomic).
10064 */
10065 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10066 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010067 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010068 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010069 NULL, type, NULL,
10070 "The item type %s must have a variety of atomic or union",
10071 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10072 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010073 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10074 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10075 xmlSchemaTypeLinkPtr member;
10076
10077 member = itemType->memberTypes;
10078 while (member != NULL) {
10079 if ((member->type->flags &
10080 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010081 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010082 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010083 NULL, type, NULL,
10084 "The item type is a union type, but the "
10085 "member type %s of this item type is not atomic",
10086 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10087 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010088 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10089 }
10090 member = member->next;
10091 }
10092 }
10093
10094 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10095 xmlSchemaFacetPtr facet;
10096 /*
10097 * This is the case if we have: <simpleType><list ..
10098 */
10099 /*
10100 * 2.3.1
10101 * 2.3.1.1 The {final} of the {item type definition} must not
10102 * contain list.
10103 */
10104 if (xmlSchemaTypeFinalContains(ctxt->schema,
10105 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010106 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010107 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010108 NULL, type, NULL,
10109 "The final of its item type %s must not contain 'list'",
10110 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10111 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010112 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10113 }
10114 /*
10115 * 2.3.1.2 The {facets} must only contain the whiteSpace
10116 * facet component.
10117 */
10118 if (type->facets != NULL) {
10119 facet = type->facets;
10120 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010121 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10122 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010123 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010124 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010125 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10126 }
10127 facet = facet->next;
10128 } while (facet != NULL);
10129 }
10130 /*
10131 * TODO: Datatypes states:
10132 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10133 * whose ·lexical space· allows space (such as string or anyURI)or
10134 * a ·union· datatype any of whose {member type definitions}'s
10135 * ·lexical space· allows space.
10136 */
10137 } else {
10138 /*
10139 * This is the case if we have: <simpleType><restriction ...
10140 */
10141 /*
10142 * 2.3.2
10143 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10144 */
10145 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010146 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010147 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010148 NULL, type, NULL,
10149 "The base type %s must be a list type",
10150 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10151 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010152 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10153 }
10154 /*
10155 * 2.3.2.2 The {final} of the {base type definition} must not
10156 * contain restriction.
10157 */
10158 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10159 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010160 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010161 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010162 NULL, type, NULL,
10163 "The final of the base type %s must not contain 'restriction'",
10164 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10165 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010166 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10167 }
10168 /*
10169 * 2.3.2.3 The {item type definition} must be validly derived
10170 * from the {base type definition}'s {item type definition} given
10171 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10172 */
10173 {
10174 xmlSchemaTypePtr baseItemType;
10175
10176 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
10177 if (baseItemType == NULL) {
10178 xmlSchemaPErr(ctxt, type->node,
10179 XML_ERR_INTERNAL_ERROR,
10180 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010181 "List simple type '%s': Failed to "
10182 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010183 type->name, type->baseType->name);
10184 return (-1);
10185 }
10186 if ((itemType != baseItemType) &&
10187 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
10188 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010189 xmlChar *strBIT = NULL, *strBT = NULL;
10190 xmlSchemaPCustomErrExt(ctxt,
10191 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
10192 NULL, type, NULL,
10193 "The item type %s is not validly derived from the "
10194 "item type %s of the base type %s",
10195 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
10196 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
10197 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10198
10199 FREE_AND_NULL(str)
10200 FREE_AND_NULL(strBIT)
10201 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010202 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
10203 }
10204 }
10205
10206 if (type->facets != NULL) {
10207 xmlSchemaFacetPtr facet;
10208 int ok = 1;
10209 /*
10210 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
10211 * and enumeration facet components are allowed among the {facets}.
10212 */
10213 facet = type->facets;
10214 do {
10215 switch (facet->type) {
10216 case XML_SCHEMA_FACET_LENGTH:
10217 case XML_SCHEMA_FACET_MINLENGTH:
10218 case XML_SCHEMA_FACET_MAXLENGTH:
10219 case XML_SCHEMA_FACET_WHITESPACE:
10220 /*
10221 * TODO: 2.5.1.2 List datatypes
10222 * The value of ·whiteSpace· is fixed to the value collapse.
10223 */
10224 case XML_SCHEMA_FACET_PATTERN:
10225 case XML_SCHEMA_FACET_ENUMERATION:
10226 break;
10227 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010228 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010229 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010230 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010231 /*
10232 * We could return, but it's nicer to report all
10233 * invalid facets.
10234 */
10235 ok = 0;
10236 }
10237 }
10238 facet = facet->next;
10239 } while (facet != NULL);
10240 if (ok == 0)
10241 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
10242 /*
10243 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
10244 * is a facet of the same kind in the {facets} of the {base type
10245 * definition} (call this BF),then the DF's {value} must be a valid
10246 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
10247 */
10248 }
10249
10250
10251 }
10252 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10253 /*
10254 * 3.1 The {member type definitions} must all have {variety} of
10255 * atomic or list.
10256 */
10257 xmlSchemaTypeLinkPtr member;
10258
10259 member = type->memberTypes;
10260 while (member != NULL) {
10261 if (((member->type->flags &
10262 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10263 ((member->type->flags &
10264 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010265 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010266 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010267 NULL, type, NULL,
10268 "The member type %s is neither an atomic, nor a list type",
10269 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10270 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010271 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
10272 }
10273 member = member->next;
10274 }
10275 /*
10276 * 3.3.1 If the {base type definition} is the ·simple ur-type
10277 * definition·
10278 */
10279 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10280 /*
10281 * 3.3.1.1 All of the {member type definitions} must have a
10282 * {final} which does not contain union.
10283 */
10284 member = type->memberTypes;
10285 while (member != NULL) {
10286 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
10287 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010288 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010289 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010290 NULL, type, NULL,
10291 "The final of member type %s contains 'union'",
10292 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10293 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010294 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
10295 }
10296 member = member->next;
10297 }
10298 /*
10299 * 3.3.1.2 The {facets} must be empty.
10300 */
10301 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010302 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010303 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010304 NULL, type, NULL,
10305 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010306 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
10307 }
10308 } else {
10309 /*
10310 * 3.3.2.1 The {base type definition} must have a {variety} of union.
10311 */
10312 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010313 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010314 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010315 NULL, type, NULL,
10316 "The base type %s is not a union type",
10317 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10318 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010319 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
10320 }
10321 /*
10322 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
10323 */
10324 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10325 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010326 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010327 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010328 NULL, type, NULL,
10329 "The final of its base type %s must not contain 'restriction'",
10330 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10331 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010332 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
10333 }
10334 /*
10335 * 3.3.2.3 The {member type definitions}, in order, must be validly
10336 * derived from the corresponding type definitions in the {base
10337 * type definition}'s {member type definitions} given the empty set,
10338 * as defined in Type Derivation OK (Simple) (§3.14.6).
10339 */
10340 {
10341 xmlSchemaTypeLinkPtr baseMember;
10342
10343 /*
10344 * OPTIMIZE: if the type is restricting, it has no local defined
10345 * member types and inherits the member types of the base type;
10346 * thus a check for equality can be skipped.
10347 */
10348 /*
10349 * TODO: Even worse: I cannot see a scenario where a restricting
10350 * union simple type can have other member types as the member
10351 * types of it's base type. This check seems not necessary with
10352 * respect to the derivation process in libxml2.
10353 */
10354 if (type->memberTypes != NULL) {
10355 member = type->memberTypes;
10356 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
10357 if ((member == NULL) && (baseMember != NULL)) {
10358 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010359 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010360 "Internal error: "
10361 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010362 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010363 "of member types in the base type\n",
10364 type->name, NULL);
10365 }
10366 while (member != NULL) {
10367 if (baseMember == NULL) {
10368 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010369 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010370 "Internal error: "
10371 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010372 "(3.3.2.3), union simple type '%s', unequal number "
10373 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010374 type->name, NULL);
10375 }
10376 if ((member->type != baseMember->type) &&
10377 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
10378 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010379 xmlChar *strBMT = NULL, *strBT = NULL;
10380
10381 xmlSchemaPCustomErrExt(ctxt,
10382 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
10383 NULL, type, NULL,
10384 "The member type %s is not validly derived from its "
10385 "corresponding member type %s of the base type %s",
10386 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
10387 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
10388 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10389 FREE_AND_NULL(str)
10390 FREE_AND_NULL(strBMT)
10391 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010392 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
10393 }
10394 member = member->next;
10395 baseMember = baseMember->next;
10396 }
10397 }
10398 }
10399 /*
10400 * 3.3.2.4 Only pattern and enumeration facet components are
10401 * allowed among the {facets}.
10402 */
10403 if (type->facets != NULL) {
10404 xmlSchemaFacetPtr facet;
10405 int ok = 1;
10406
10407 facet = type->facets;
10408 do {
10409 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
10410 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010411 xmlSchemaPIllegalFacetListUnionErr(ctxt,
10412 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
10413 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010414 ok = 0;
10415 }
10416 facet = facet->next;
10417 } while (facet != NULL);
10418 if (ok == 0)
10419 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
10420
10421 }
10422 /*
10423 * TODO: 3.3.2.5 (facet derivation)
10424 */
10425 }
10426 }
10427
10428 return (0);
10429}
10430
10431/**
10432 * xmlSchemaCheckSRCSimpleType:
10433 * @ctxt: the schema parser context
10434 * @type: the simple type definition
10435 *
10436 * Checks crc-simple-type constraints.
10437 *
10438 * Returns 0 if the constraints are satisfied,
10439 * if not a positive error code and -1 on internal
10440 * errors.
10441 */
10442static int
10443xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
10444 xmlSchemaTypePtr type)
10445{
10446 /*
10447 * NOTE: src-simple-type 2-4 are redundant, since the checks
10448 * were are done for the corresponding <restriction>, <list> and <union>
10449 * elements, but W3C wants a <simpleType> error as well, so it gets one.
10450 * Maby this can be skipped in the future, if we get sure it's not needed.
10451 */
10452 if (type->subtypes == NULL) {
10453 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010454 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010455 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010456 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010457 type->name, NULL);
10458 return (-1);
10459 }
10460 /*
10461 * src-simple-type.1 The corresponding simple type definition, if any,
10462 * must satisfy the conditions set out in Constraints on Simple Type
10463 * Definition Schema Components (§3.14.6).
10464 */
10465 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
10466 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
10467 /*
10468 * TODO: Removed this, since it got annoying to get an
10469 * extra error report, if anything failed until now.
10470 * Enable this if needed.
10471 */
10472 /*
10473 xmlSchemaPErr(ctxt, type->node,
10474 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010475 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010476 "on simple type definitions.\n",
10477 type->name, NULL);
10478 */
10479 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
10480 }
10481
10482 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
10483 /*
10484 * src-simple-type.2 If the <restriction> alternative is chosen,
10485 * either it must have a base [attribute] or a <simpleType> among its
10486 * [children], but not both.
10487 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010488 /*
10489 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
10490 * NOTE: This was removed, since this will be already handled
10491 * in the parse function for <restriction>.
10492 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010493 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
10494 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
10495 * an itemType [attribute] or a <simpleType> among its [children],
10496 * but not both.
10497 * NOTE: baseType is set to the local simple type definiton,
10498 * if existent, at parse time. This is a hack and not nice.
10499 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010500 /*
10501 * TODO: Remove this, and add the check to the parse function of <list>.
10502 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010503 if (((type->subtypes->base == NULL) &&
10504 (type->baseType == NULL)) ||
10505 ((type->subtypes->base != NULL) &&
10506 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010507 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010508 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010509 NULL, type, NULL,
10510 "Either the attribute 'itemType' or the <simpleType> child "
10511 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010512 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
10513 }
10514
10515
10516 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
10517 xmlSchemaTypeLinkPtr member;
10518 xmlSchemaTypePtr ancestor, anySimpleType;
10519
10520 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10521
10522 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
10523 * the <union> alternative is chosen, there must not be any entries
10524 * in the memberTypes [attribute] at any depth which resolve to the
10525 * component corresponding to the <simpleType>.
10526 */
10527 member = type->memberTypes;
10528 while (member != NULL) {
10529 ancestor = member->type;
10530 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
10531 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10532 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
10533 if (ancestor == anySimpleType)
10534 break;
10535 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010536 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010537 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010538 NULL, type, NULL,
10539 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010540 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
10541 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10542 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000010543 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000010544 * type as item type, which in turn has a list ST as member
10545 * type, we will assume this here as well, since this check
10546 * was not yet performed.
10547 */
10548
10549 }
10550 ancestor = ancestor->baseType;
10551 }
10552 member = member->next;
10553 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010554 }
10555
10556 return (0);
10557}
10558
William M. Brack2f2a6632004-08-20 23:09:47 +000010559#if 0 /* Not yet used code for CT schema validation */
10560static int
10561xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
10562 const xmlChar * value,
10563 xmlSchemaTypePtr type,
10564 int fireErrors)
10565{
10566 int ret;
10567 /*
10568 * 3.14.4 Simple Type Definition Validation Rules
10569 * Validation Rule: String Valid
10570 */
10571 /*
10572 * 1 It is schema-valid with respect to that definition as defined
10573 * by Datatype Valid in [XML Schemas: Datatypes].
10574 */
10575 ctxt->type = type;
10576 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, fireErrors, 1, 1);
10577 return (ret);
10578 /*
10579 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
10580 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
10581 * the string must be a ·declared entity name·.
10582 */
10583 /*
10584 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
10585 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
10586 * then every whitespace-delimited substring of the string must be a ·declared
10587 * entity name·.
10588 */
10589 /*
10590 * 2.3 otherwise no further condition applies.
10591 */
10592
10593 return (0);
10594}
10595
10596
10597static int
10598xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr ctxt,
10599 xmlSchemaElementPtr elemDecl)
10600{
10601 xmlSchemaTypePtr typeDef;
10602 if (elemDecl->value == NULL)
10603 return (0);
10604 if (elemDecl->subtypes == NULL) {
10605 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010606 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010607 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
10608 "Internal error: xmlSchemaCheckCOSValidDefault, "
10609 "the element decl. '%s' has no type assigned", elemDecl->name);
10610 return (-1);
10611 }
10612 typeDef = elemDecl->subtypes;
10613 if ((typeDef->type == XML_SCHEMA_TYPE_SIMPLE) ||
10614 ((typeDef->type == XML_SCHEMA_TYPE_COMPLEX) &&
10615 ((typeDef->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10616 (typeDef->contentType == XML_SCHEMA_CONTENT_BASIC)))) {
10617 xmlSchemaValidCtxtPtr vctxt;
10618 xmlAttrPtr attr;
10619 int ret = 0;
10620 /*
10621 * 1 If the type definition is a simple type definition, then the string
10622 * must be ·valid· with respect to that definition as defined by String
10623 * Valid (§3.14.4).
10624 */
10625 /*
10626 * 2.2.1 If the {content type} is a simple type definition, then the
10627 * string must be ·valid· with respect to that simple type definition
10628 * as defined by String Valid (§3.14.4).
10629 */
10630 /*
10631 * TODO: ?
10632 */
10633
10634 vctxt = xmlSchemaNewValidCtxt(NULL);
10635 if (vctxt == NULL) {
10636 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010637 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010638 "Internal error: xmlSchemaCheckCOSValidDefault, "
10639 "creation of a new validation context failed.\n",
10640 NULL, NULL);
10641 return (-1);
10642 }
10643 /*
10644 * TODO: This won't work.
10645 */
10646 if (typeDef->type == XML_SCHEMA_TYPE_SIMPLE)
10647 ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0);
10648 if (ret > 0) {
10649 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10650 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10651 else
10652 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10653 if (ctxt != NULL) {
10654 xmlSchemaPSimpleTypeErr(ctxt,
10655 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10656 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10657 elemDecl->subtypes, NULL, elemDecl->value,
10658 NULL, NULL, NULL);
10659 return (ctxt->err);
10660 }
10661 ret = ctxt->err;
10662 } else if (ret < 0) {
10663 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010664 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010665 "Internal error: xmlSchemaCheckCOSValidDefault, "
10666 "while validating the default/fixed value.\n",
10667 NULL, NULL);
10668 }
10669 xmlSchemaFreeValidCtxt(vctxt);
10670 return (ret);
10671 } else {
10672 /*
10673 * Complex type.
10674 *
10675 * 2.1 its {content type} must be a simple type definition or mixed.
10676 */
10677 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10678 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC) &&
10679 (elemDecl->subtypes->contentType == XML_SCHEMA_CONTENT_MIXED)) {
10680 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10681 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
10682 "The content type must be a simple type definition or mixed.",
10683 NULL);
10684 return(ctxt->err);
10685 }
10686 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10687 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC)) {
10688 xmlSchemaValidCtxtPtr vctxt;
10689 xmlAttrPtr attr;
10690 int ret;
10691
10692 /* TODO: Avoid creation of a new context. */
10693 vctxt = xmlSchemaNewValidCtxt(NULL);
10694 if (vctxt == NULL) {
10695 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010696 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010697 "Internal error: xmlSchemaCheckCOSValidDefault, "
10698 "creation of a new validation context failed.\n",
10699 NULL, NULL);
10700 return (-1);
10701 }
10702 vctxt->type = elemDecl->subtypes;
10703 ret = xmlSchemaValidateSimpleTypeValue(vctxt, elemDecl->value, 0, 1, 1);
10704 if (ret > 0) {
10705 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10706 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10707 else
10708 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10709 if (ctxt != NULL) {
10710 xmlSchemaPSimpleTypeErr(ctxt,
10711 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10712 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10713 elemDecl->subtypes, NULL, elemDecl->value,
10714 NULL, NULL, NULL);
10715 return (ctxt->err);
10716 }
10717 ret = ctxt->err;
10718 } else if (ret < 0) {
10719 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010720 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010721 "Internal error: xmlSchemaCheckCOSValidDefault, "
10722 "while validating the default/fixed value.\n",
10723 NULL, NULL);
10724 }
10725 xmlSchemaFreeValidCtxt(vctxt);
10726 return (ret);
10727 } else {
10728 /*
10729 * 2.2.2 If the {content type} is mixed, then the {content type}'s
10730 * particle must be ·emptiable· as defined by Particle Emptiable
10731 * (§3.9.6).
10732 */
10733 /*
10734 * TODO: Implement this.
10735 */
10736 }
10737 }
10738
10739 return (0);
10740}
10741
10742/**
10743 * xmlSchemaGetSTContentOfCT:
10744 * @ctxt: the schema parser context
10745 * @type: the complex type definition
10746 *
10747 *
10748 * Returns the corresponding simple type for the content of
10749 * the complex type.
10750 */
10751static xmlSchemaTypePtr
10752xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
10753 xmlSchemaTypePtr type)
10754{
10755 xmlSchemaTypePtr orig = type, anyType;
10756
10757 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10758 while ((type != NULL) && (type != anyType) &&
10759 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10760 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
10761 return(type);
10762 type = type->baseType;
10763 }
10764 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010765 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010766 NULL, orig, NULL,
10767 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
10768 "no simple type for the content of complex type '%s' could be "
10769 "computed", orig->name);
10770 return (NULL);
10771}
10772
10773
10774static xmlSchemaTypePtr
10775xmlSchemaGetContentType(xmlSchemaParserCtxtPtr ctxt,
10776 xmlSchemaTypePtr type)
10777{
10778 if (type->baseType == NULL) {
10779 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010780 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010781 NULL, type, NULL,
10782 "Internal error: xmlSchemaGetContentType, "
10783 "the complex type '%s' has no base type", type->name);
10784 return (NULL);
10785 }
10786 if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
10787 if ((type->baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10788 ((type->baseType->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10789 (type->baseType->contentType == XML_SCHEMA_CONTENT_BASIC)) &&
10790 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
10791 /*
10792 * 1 If the type definition ·resolved· to by the ·actual value· of
10793 * the base [attribute] is a complex type definition whose own
10794 * {content type} is a simple type definition and the <restriction>
10795 * alternative is chosen
10796 */
10797
10798
10799 }
10800 } else {
10801
10802 }
10803}
10804
10805/**
10806 * xmlSchemaCheckCOSCTExtends:
10807 * @ctxt: the schema parser context
10808 * @type: the complex type definition
10809 *
10810 * Schema Component Constraint: Derivation Valid (Extension)
10811 *
10812 * Returns 0 if the constraints are satisfied, a positive
10813 * error code if not and -1 if an internal error occured.
10814 */
10815static int
10816xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
10817 xmlSchemaTypePtr type)
10818{
10819 xmlSchemaTypePtr base;
10820 /*
10821 * 1 If the {base type definition} is a complex type definition,
10822 * then all of the following must be true:
10823 */
10824 base = type->baseType;
10825 if (base == NULL) {
10826 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010827 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010828 NULL, type, NULL,
10829 "Internal error: xmlSchemaCheckCOSCTExtends, "
10830 "the complex type '%s' has no base type", type->name);
10831 return (-1);
10832 }
10833 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
10834 /*
10835 * 1.1 The {final} of the {base type definition} must not
10836 * contain extension.
10837 */
10838 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
10839 xmlSchemaPCustomErr(ctxt,
10840 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
10841 NULL, type, NULL,
10842 "The 'final' of the base type definition "
10843 "contains extension", NULL);
10844 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
10845 }
10846 /*
10847 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
10848 * of the complex type definition itself, that is, for every attribute
10849 * use in the {attribute uses} of the {base type definition}, there
10850 * must be an attribute use in the {attribute uses} of the complex
10851 * type definition itself whose {attribute declaration} has the same
10852 * {name}, {target namespace} and {type definition} as its attribute
10853 * declaration
10854 *
10855 * NOTE: This will be already satisfied by the way the attribute uses
10856 * are extended in xmlSchemaBuildAttributeValidation; thus this check
10857 * is not needed.
10858 */
10859
10860 /*
10861 * 1.3 If it has an {attribute wildcard}, the complex type definition
10862 * must also have one, and the base type definition's {attribute
10863 * wildcard}'s {namespace constraint} must be a subset of the complex
10864 * type definition's {attribute wildcard}'s {namespace constraint},
10865 * as defined by Wildcard Subset (§3.10.6).
10866 *
10867 * This is already checked in xmlSchemaBuildAttributeValidation; thus
10868 * this check is not needed.
10869 */
10870
10871 /*
10872 * 1.4 One of the following must be true:
10873 *
10874 * 1.4.1 The {content type} of the {base type definition} and the
10875 * {content type} of the complex type definition itself must be the same
10876 * simple type definition
10877 */
10878
10879
10880
10881 } else {
10882 /*
10883 * 2 If the {base type definition} is a simple type definition,
10884 * then all of the following must be true:
10885 */
10886 /*
10887 * 2.1 The {content type} must be the same simple type definition.
10888 */
10889 /*
10890 * 2.2 The {final} of the {base type definition} must not contain
10891 * extension
10892 */
10893 }
10894
10895}
10896
10897#endif
10898
Daniel Veillard01fa6152004-06-29 17:04:39 +000010899/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010900 * xmlSchemaTypeFixup:
10901 * @typeDecl: the schema type definition
10902 * @ctxt: the schema parser context
10903 *
10904 * Fixes the content model of the type.
10905 */
10906static void
10907xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010908 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000010909{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010910 xmlSchemaTypePtr ctxtType;
10911
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010912 if (typeDecl == NULL)
10913 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010914 /*
10915 * Do not allow the following types to be typefixed, prior to
10916 * the corresponding simple/complex types.
10917 */
10918 if (ctxt->ctxtType == NULL) {
10919 switch (typeDecl->type) {
10920 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10921 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10922 case XML_SCHEMA_TYPE_UNION:
10923 case XML_SCHEMA_TYPE_RESTRICTION:
10924 case XML_SCHEMA_TYPE_EXTENSION:
10925 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010926 default:
10927 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010928 }
10929 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010930 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010931 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010932 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010933 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010934 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
10935 if (typeDecl->subtypes != NULL) {
10936 if (typeDecl->subtypes->contentType ==
10937 XML_SCHEMA_CONTENT_UNKNOWN) {
10938 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
10939 NULL);
10940 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010941 typeDecl->contentType =
10942 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010943 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010944 break;
10945 }
10946 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010947 xmlSchemaTypePtr base = NULL;
10948
10949 ctxt->ctxtType->flags |=
10950 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
William M. Brack2f2a6632004-08-20 23:09:47 +000010951 if (typeDecl->baseType != NULL)
10952 base = typeDecl->baseType;
10953 else if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010954 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010955 xmlSchemaGetType(ctxt->schema, typeDecl->base,
10956 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010957 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010958 xmlSchemaPResCompAttrErr(ctxt,
10959 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000010960 NULL, NULL,
10961 (xmlNodePtr) xmlSchemaGetPropNode(typeDecl->node, "base"),
Daniel Veillardc0826a72004-08-10 14:17:33 +000010962 "base", typeDecl->base, typeDecl->baseNs,
10963 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010964 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000010965 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010966 xmlSchemaTypeFixup(base, ctxt, NULL);
10967 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010968 }
10969 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010970 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
10971 /*
10972 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000010973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010974 /*
10975 * Content type.
10976 */
10977 if (typeDecl->subtypes == NULL)
10978 /* 1.1.1 */
10979 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10980 else if ((typeDecl->subtypes->subtypes == NULL) &&
10981 ((typeDecl->subtypes->type ==
10982 XML_SCHEMA_TYPE_ALL)
10983 || (typeDecl->subtypes->type ==
10984 XML_SCHEMA_TYPE_SEQUENCE)))
10985 /* 1.1.2 */
10986 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10987 else if ((typeDecl->subtypes->type ==
10988 XML_SCHEMA_TYPE_CHOICE)
10989 && (typeDecl->subtypes->subtypes == NULL))
10990 /* 1.1.3 */
10991 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10992 else {
10993 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010994 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000010995 XML_SCHEMA_CONTENT_ELEMENTS;
10996 }
10997 } else {
10998 /*
10999 * SimpleType restriction.
11000 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011001 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011002 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011003 break;
11004 }
11005 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011006 xmlSchemaTypePtr base = NULL;
11007 xmlSchemaContentType explicitContentType;
11008
11009 /*
11010 * An extension does exist on a complexType only.
11011 */
11012 ctxt->ctxtType->flags |=
11013 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11014 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011015 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011016 xmlSchemaPCustomErr(ctxt,
11017 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
11018 NULL, typeDecl, typeDecl->node,
11019 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000011020 return;
11021 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011022 if (typeDecl->base != NULL) {
11023 base =
11024 xmlSchemaGetType(ctxt->schema, typeDecl->base,
11025 typeDecl->baseNs);
11026 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011027 xmlSchemaPResCompAttrErr(ctxt,
11028 XML_SCHEMAP_SRC_RESOLVE,
11029 NULL, typeDecl, typeDecl->node,
11030 "base", typeDecl->base, typeDecl->baseNs,
11031 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011032 } else if (base->contentType ==
11033 XML_SCHEMA_CONTENT_UNKNOWN) {
11034 typeDecl->recurse = 1;
11035 xmlSchemaTypeFixup(base, ctxt, NULL);
11036 typeDecl->recurse = 0;
11037 }
11038 /*
11039 * The type definition ·resolved· to by the ·actual
11040 * value· of the base [attribute]
11041 */
11042 ctxt->ctxtType->baseType = base;
11043 /*
11044 * TODO: This one is still needed for computation of
11045 * the content model by xmlSchemaBuildAContentModel.
11046 * Try to get rid of it.
11047 */
11048 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011049 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011050 if ((typeDecl->subtypes != NULL) &&
11051 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
11052 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
11053
11054 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
11055 if (typeDecl->subtypes == NULL)
11056 /* 1.1.1 */
11057 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11058 else if ((typeDecl->subtypes->subtypes == NULL) &&
11059 ((typeDecl->subtypes->type ==
11060 XML_SCHEMA_TYPE_ALL)
11061 || (typeDecl->subtypes->type ==
11062 XML_SCHEMA_TYPE_SEQUENCE)))
11063 /* 1.1.2 */
11064 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11065 else if ((typeDecl->subtypes->type ==
11066 XML_SCHEMA_TYPE_CHOICE)
11067 && (typeDecl->subtypes->subtypes == NULL))
11068 /* 1.1.3 */
11069 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11070 if (base != NULL) {
11071 /* It will be reported later, if the base is missing. */
11072 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
11073 /* 2.1 */
11074 typeDecl->contentType = base->contentType;
11075 } else if (base->contentType ==
11076 XML_SCHEMA_CONTENT_EMPTY) {
11077 /* 2.2 imbitable ! */
11078 typeDecl->contentType =
11079 XML_SCHEMA_CONTENT_ELEMENTS;
11080 } else {
11081 /* 2.3 imbitable pareil ! */
11082 typeDecl->contentType =
11083 XML_SCHEMA_CONTENT_ELEMENTS;
11084 }
11085 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011086 break;
11087 }
11088 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011089 ctxtType = ctxt->ctxtType;
11090 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011091 if ((typeDecl->subtypes == NULL) ||
11092 ((typeDecl->subtypes->type !=
11093 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
11094 (typeDecl->subtypes->type !=
11095 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
11096 /*
11097 * This case is understood as shorthand for complex
11098 * content restricting the ur-type definition, and
11099 * the details of the mappings should be modified as
11100 * necessary.
11101 */
11102 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11103 typeDecl->flags |=
11104 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11105 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011106 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011107 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011108 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11109 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011110 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011111 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011112 if ((typeDecl->subtypes != NULL) &&
11113 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011114 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011115 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011116 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011117 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011118 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011119 typeDecl->contentType =
11120 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011121 } else {
11122 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011123 typeDecl->contentType =
11124 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011125 }
11126 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011127 }
11128 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011129 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011130 break;
11131 }
11132 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
11133 if (typeDecl->subtypes == NULL) {
11134 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011135 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11136 typeDecl->contentType =
11137 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011138 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011139 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011140 typeDecl->contentType =
11141 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000011142 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011143 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
11144 NULL);
11145 if (typeDecl->subtypes != NULL)
11146 typeDecl->contentType =
11147 typeDecl->subtypes->contentType;
11148 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011149 /*
11150 * Removed due to implementation of the build of attribute uses.
11151 */
11152 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011153 if (typeDecl->attributes == NULL)
11154 typeDecl->attributes =
11155 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011156 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011157 }
11158 break;
11159 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011160 case XML_SCHEMA_TYPE_SIMPLE:
11161 /*
11162 * Simple Type Definition Schema Component
11163 *
11164 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011165 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011166 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11167 if (typeDecl->subtypes->contentType ==
11168 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011169 ctxt->ctxtType = typeDecl;
11170 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011171 }
11172 /* Fixup base type */
11173 if ((typeDecl->baseType != NULL) &&
11174 (typeDecl->baseType->contentType ==
11175 XML_SCHEMA_CONTENT_UNKNOWN)) {
11176 /* OPTIMIZE: Actually this one will never by hit, since
11177 * the base type is already type-fixed in <restriction>.
11178 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011179 ctxt->ctxtType = typeDecl;
11180 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011181 }
11182 /* Base type:
11183 * 2 If the <list> or <union> alternative is chosen,
11184 * then the ·simple ur-type definition·.
11185 */
11186 if (typeDecl->subtypes->type ==
11187 XML_SCHEMA_TYPE_LIST) {
11188 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11189 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11190 } else if (typeDecl->subtypes->type ==
11191 XML_SCHEMA_TYPE_UNION) {
11192 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11193 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11194 } else if (typeDecl->subtypes->type ==
11195 XML_SCHEMA_TYPE_RESTRICTION) {
11196 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
11197
11198 /*
11199 * Variety
11200 * If the <restriction> alternative is chosen, then the
11201 * {variety} of the {base type definition}.
11202 */
11203 if (typeDecl->baseType != NULL) {
11204 if (typeDecl->baseType->flags &
11205 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
11206 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
11207 else if (typeDecl->baseType->flags &
11208 XML_SCHEMAS_TYPE_VARIETY_LIST)
11209 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11210 else if (typeDecl->baseType->flags &
11211 XML_SCHEMAS_TYPE_VARIETY_UNION)
11212 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11213 /*
11214 * Schema Component Constraint: Simple Type Restriction
11215 * (Facets)
11216 * NOTE: Satisfaction of 1 and 2 arise from the fixup
11217 * applied beforehand.
11218 *
11219 * 3 The {facets} of R are the union of S and the {facets}
11220 * of B, eliminating duplicates. To eliminate duplicates,
11221 * when a facet of the same kind occurs in both S and the
11222 * {facets} of B, the one in the {facets} of B is not
11223 * included, with the exception of enumeration and pattern
11224 * facets, for which multiple occurrences with distinct values
11225 * are allowed.
11226 */
11227 if (typeDecl->baseType->facetSet != NULL) {
11228 last = typeDecl->facetSet;
11229 if (last != NULL)
11230 while (last->next != NULL)
11231 last = last->next;
11232 cur = typeDecl->baseType->facetSet;
11233 for (; cur != NULL; cur = cur->next) {
11234 /*
11235 * Base patterns won't be add here:
11236 * they are ORed in a type and
11237 * ANDed in derived types. This will
11238 * happed at validation level by
11239 * walking the base axis of the type.
11240 */
11241 if (cur->facet->type ==
11242 XML_SCHEMA_FACET_PATTERN)
11243 continue;
11244 facet = NULL;
11245 if ((typeDecl->facetSet != NULL) &&
11246 (cur->facet->type !=
11247 XML_SCHEMA_FACET_PATTERN) &&
11248 (cur->facet->type !=
11249 XML_SCHEMA_FACET_ENUMERATION)) {
11250 facet = typeDecl->facetSet;
11251 do {
11252 if (cur->facet->type ==
11253 facet->facet->type)
11254 break;
11255 facet = facet->next;
11256 } while (facet != NULL);
11257 }
11258 if (facet == NULL) {
11259 facet = (xmlSchemaFacetLinkPtr)
11260 xmlMalloc(sizeof(xmlSchemaFacetLink));
11261 if (facet == NULL) {
11262 xmlSchemaPErrMemory(ctxt,
11263 "fixing simpleType", NULL);
11264 return;
11265 }
11266 facet->facet = cur->facet;
11267 facet->next = NULL;
11268 if (last == NULL)
11269 typeDecl->facetSet = facet;
11270 else
11271 last->next = facet;
11272 last = facet;
11273 }
11274 }
11275 }
11276 }
11277 }
11278 /*
11279 * Check constraints.
11280 */
11281 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011282 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011283 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011284 case XML_SCHEMA_TYPE_SEQUENCE:
11285 case XML_SCHEMA_TYPE_GROUP:
11286 case XML_SCHEMA_TYPE_ALL:
11287 case XML_SCHEMA_TYPE_CHOICE:
11288 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11289 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011290 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +000011291 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011292 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11293 break;
11294 case XML_SCHEMA_TYPE_UNION:
11295 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
11296 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11297 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 case XML_SCHEMA_TYPE_BASIC:
11299 case XML_SCHEMA_TYPE_ANY:
11300 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011301 case XML_SCHEMA_TYPE_UR:
11302 case XML_SCHEMA_TYPE_ELEMENT:
11303 case XML_SCHEMA_TYPE_ATTRIBUTE:
11304 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000011305 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011307 case XML_SCHEMA_FACET_MININCLUSIVE:
11308 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11309 case XML_SCHEMA_FACET_MAXINCLUSIVE:
11310 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11311 case XML_SCHEMA_FACET_TOTALDIGITS:
11312 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11313 case XML_SCHEMA_FACET_PATTERN:
11314 case XML_SCHEMA_FACET_ENUMERATION:
11315 case XML_SCHEMA_FACET_WHITESPACE:
11316 case XML_SCHEMA_FACET_LENGTH:
11317 case XML_SCHEMA_FACET_MAXLENGTH:
11318 case XML_SCHEMA_FACET_MINLENGTH:
11319 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011320 if (typeDecl->subtypes != NULL)
11321 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322 break;
11323 }
11324 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011325#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011326 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011327 xmlGenericError(xmlGenericErrorContext,
11328 "Type of %s : %s:%d :", name,
11329 typeDecl->node->doc->URL,
11330 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011331 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011332 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011333 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011334 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335 case XML_SCHEMA_CONTENT_SIMPLE:
11336 xmlGenericError(xmlGenericErrorContext, "simple\n");
11337 break;
11338 case XML_SCHEMA_CONTENT_ELEMENTS:
11339 xmlGenericError(xmlGenericErrorContext, "elements\n");
11340 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011341 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011342 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
11343 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011344 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011345 xmlGenericError(xmlGenericErrorContext, "empty\n");
11346 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011347 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348 xmlGenericError(xmlGenericErrorContext, "mixed\n");
11349 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011350 /* Removed, since not used. */
11351 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000011352 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011353 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
11354 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011355 */
Daniel Veillard8651f532002-04-17 09:06:27 +000011356 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011357 xmlGenericError(xmlGenericErrorContext, "basic\n");
11358 break;
11359 default:
11360 xmlGenericError(xmlGenericErrorContext,
11361 "not registered !!!\n");
11362 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011363 }
11364#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011365}
11366
11367/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011368 * xmlSchemaCheckFacet:
11369 * @facet: the facet
11370 * @typeDecl: the schema type definition
11371 * @ctxt: the schema parser context or NULL
11372 * @name: name of the type
11373 *
11374 * Checks the default values types, especially for facets
11375 *
11376 * Returns 0 if okay or -1 in cae of error
11377 */
11378int
11379xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011380 xmlSchemaTypePtr typeDecl,
11381 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011382{
11383 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
11384 int ret = 0;
11385
11386 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011387 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011388 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011389 }
11390 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011391 case XML_SCHEMA_FACET_MININCLUSIVE:
11392 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11393 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011394 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11395 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011396 /*
11397 * Okay we need to validate the value
11398 * at that point.
11399 */
11400 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011401 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011402
11403 /* 4.3.5.5 Constraints on enumeration Schema Components
11404 * Schema Component Constraint: enumeration valid restriction
11405 * It is an ·error· if any member of {value} is not in the
11406 * ·value space· of {base type definition}.
11407 *
11408 * minInclusive, maxInclusive, minExclusive, maxExclusive:
11409 * The value ·must· be in the
11410 * ·value space· of the ·base type·.
11411 */
11412 /*
11413 * This function is intended to deliver a compiled value
11414 * on the facet. In XML Schemas the type holding a facet,
11415 * cannot be a built-in type. Thus to ensure that other API
11416 * calls (relaxng) do work, if the given type is a built-in
11417 * type, we will assume that the given built-in type *is
11418 * already* the base type.
11419 */
11420 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
11421 base = typeDecl->baseType;
11422 if (base == NULL) {
11423 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011424 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011425 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011426 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011427 typeDecl->name, NULL);
11428 return (-1);
11429 }
11430 } else
11431 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011432 /*
11433 * TODO: Try to avoid creating a new context.
11434 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011435 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011436 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011437 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011438 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011439 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011440 "creating a new validation context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011441 NULL, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011442 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011443 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011444 vctxt->type = base;
11445 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011446 facet->val = vctxt->value;
11447 vctxt->value = NULL;
11448 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011449 /* error code */
11450 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011451 xmlSchemaPErrExt(ctxt, facet->node,
11452 XML_SCHEMAP_INVALID_FACET,
11453 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011454 "Type definition '%s': The value '%s' of the "
11455 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011456 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011457 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011458 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011459 }
11460 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011461 } else if (ret < 0) {
11462 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011463 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011464 NULL, NULL, NULL,
11465 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011466 "failed to validate the value '%s' name of the "
11467 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011468 facet->value,
11469 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
11470 base->name, NULL, NULL);
11471 ret = -1;
11472 }
11473 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011474 break;
11475 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011476 case XML_SCHEMA_FACET_PATTERN:
11477 facet->regexp = xmlRegexpCompile(facet->value);
11478 if (facet->regexp == NULL) {
11479 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011480 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011481 "Type definition '%s': The value '%s' of the "
11482 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011483 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011484 ret = -1;
11485 }
11486 break;
11487 case XML_SCHEMA_FACET_TOTALDIGITS:
11488 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11489 case XML_SCHEMA_FACET_LENGTH:
11490 case XML_SCHEMA_FACET_MAXLENGTH:
11491 case XML_SCHEMA_FACET_MINLENGTH:{
11492 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011493
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011494 tmp =
11495 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
11496 facet->value,
11497 &facet->val);
11498 if (tmp != 0) {
11499 /* error code */
11500 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011501 xmlSchemaPErrExt(ctxt, facet->node,
11502 XML_SCHEMAP_INVALID_FACET_VALUE,
11503 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011504 "Type definition '%s': The value '%s' of the "
11505 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011506 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011507 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011508 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011509 }
11510 ret = -1;
11511 }
11512 break;
11513 }
11514 case XML_SCHEMA_FACET_WHITESPACE:{
11515 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
11516 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
11517 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
11518 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
11519 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
11520 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
11521 } else {
11522 if (ctxt != NULL) {
11523 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011524 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011525 "Type definition '%s': The value '%s' of the "
11526 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011527 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011528 }
11529 ret = -1;
11530 }
11531 }
11532 default:
11533 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011534 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011535 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011536}
11537
11538/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011539 * xmlSchemaCheckDefaults:
11540 * @typeDecl: the schema type definition
11541 * @ctxt: the schema parser context
11542 *
11543 * Checks the default values types, especially for facets
11544 */
11545static void
11546xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011547 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011548{
Daniel Veillard4255d502002-04-16 15:50:10 +000011549 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011550 name = typeDecl->name;
11551 /*
11552 * NOTE: It is intended to use the facets list, instead
11553 * of facetSet.
11554 */
11555 if (typeDecl->facets != NULL) {
11556 xmlSchemaFacetPtr facet = typeDecl->facets;
11557
11558 while (facet != NULL) {
11559 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
11560 facet = facet->next;
11561 }
11562 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011563}
11564
11565/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000011566 * xmlSchemaAttrGrpFixup:
11567 * @attrgrpDecl: the schema attribute definition
11568 * @ctxt: the schema parser context
11569 * @name: the attribute name
11570 *
11571 * Fixes finish doing the computations on the attributes definitions
11572 */
11573static void
Daniel Veillard3646d642004-06-02 19:19:14 +000011574xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011575 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000011576{
11577 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011578 name = attrgrp->name;
11579 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011580 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000011581 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011582 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000011583
Daniel Veillardc0826a72004-08-10 14:17:33 +000011584 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
11585 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011586 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011587 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011588 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011589 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
11590 "ref", attrgrp->ref, attrgrp->refNs,
11591 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011592 return;
11593 }
11594 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011595 attrgrp->attributes = ref->attributes;
11596 attrgrp->attributeWildcard = ref->attributeWildcard;
11597 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000011598}
11599
11600/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011601 * xmlSchemaAttrFixup:
11602 * @attrDecl: the schema attribute definition
11603 * @ctxt: the schema parser context
11604 * @name: the attribute name
11605 *
11606 * Fixes finish doing the computations on the attributes definitions
11607 */
11608static void
11609xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011610 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011611{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011612 /*
11613 * TODO: If including this is done twice (!) for every attribute.
11614 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011615 /*
11616 * The simple type definition corresponding to the <simpleType> element
11617 * information item in the [children], if present, otherwise the simple
11618 * type definition ·resolved· to by the ·actual value· of the type
11619 * [attribute], if present, otherwise the ·simple ur-type definition·.
11620 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011621 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
11622 return;
11623 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000011624 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011625 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000011626 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011627 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011628 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011629 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011630
Daniel Veillard01fa6152004-06-29 17:04:39 +000011631 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
11632 attrDecl->typeNs);
11633 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011634 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011635 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011636 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11637 "type", attrDecl->typeName, attrDecl->typeNs,
11638 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011639 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011640 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011641 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011642 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000011643
Daniel Veillardc0826a72004-08-10 14:17:33 +000011644 /*
11645 * TODO: Evaluate, what errors could occur if the declaration is not
11646 * found. It might be possible that the "typefixup" might crash if
11647 * no ref declaration was found.
11648 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011649 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011650 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011651 xmlSchemaPResCompAttrErr(ctxt,
11652 XML_SCHEMAP_SRC_RESOLVE,
11653 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11654 "ref", attrDecl->ref, attrDecl->refNs,
11655 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011656 return;
11657 }
11658 xmlSchemaAttrFixup(ref, ctxt, NULL);
11659 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011660 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011661 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000011662 }
11663}
11664
11665/**
11666 * xmlSchemaParse:
11667 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011668 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011669 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000011670 * XML Shema struture which can be used to validate instances.
11671 * *WARNING* this interface is highly subject to change
11672 *
11673 * Returns the internal XML Schema structure built from the resource or
11674 * NULL in case of error
11675 */
11676xmlSchemaPtr
11677xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
11678{
11679 xmlSchemaPtr ret = NULL;
11680 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011681 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011682 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011683 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011684
11685 xmlSchemaInitTypes();
11686
Daniel Veillard6045c902002-10-09 21:13:59 +000011687 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000011688 return (NULL);
11689
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011690 nberrors = ctxt->nberrors;
11691 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011692 ctxt->counter = 0;
11693 ctxt->container = NULL;
11694
11695 /*
11696 * First step is to parse the input document into an DOM/Infoset
11697 */
Daniel Veillard6045c902002-10-09 21:13:59 +000011698 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011699 doc = xmlReadFile((const char *) ctxt->URL, NULL,
11700 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011701 if (doc == NULL) {
11702 xmlSchemaPErr(ctxt, NULL,
11703 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011704 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011705 ctxt->URL, NULL);
11706 return (NULL);
11707 }
Daniel Veillard6045c902002-10-09 21:13:59 +000011708 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011709 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
11710 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011711 if (doc == NULL) {
11712 xmlSchemaPErr(ctxt, NULL,
11713 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011714 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011715 NULL, NULL);
11716 return (NULL);
11717 }
11718 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000011719 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000011720 } else if (ctxt->doc != NULL) {
11721 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011722 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000011723 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011724 xmlSchemaPErr(ctxt, NULL,
11725 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011726 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011727 NULL, NULL);
11728 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011729 }
11730
11731 /*
11732 * Then extract the root and Schema parse it
11733 */
11734 root = xmlDocGetRootElement(doc);
11735 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011736 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11737 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011738 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000011739 if (!preserve) {
11740 xmlFreeDoc(doc);
11741 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011742 return (NULL);
11743 }
11744
11745 /*
11746 * Remove all the blank text nodes
11747 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011748 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000011749
11750 /*
11751 * Then do the parsing for good
11752 */
11753 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000011754 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000011755 if (!preserve) {
11756 xmlFreeDoc(doc);
11757 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011758 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000011759 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011760 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011761 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000011762 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011763 ctxt->ctxtType = NULL;
11764 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011765 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011766 * Then fixup all attributes declarations
11767 */
11768 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
11769
11770 /*
11771 * Then fixup all attributes group declarations
11772 */
11773 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
11774 ctxt);
11775
11776 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000011777 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000011778 */
11779 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
11780
11781 /*
11782 * Then fix references of element declaration; apply constraints.
11783 */
11784 xmlHashScanFull(ret->elemDecl,
11785 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011786
11787 /*
11788 * Then build the content model for all elements
11789 */
11790 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011791 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011792
11793 /*
11794 * Then check the defaults part of the type like facets values
11795 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011796 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
11797 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011798
Daniel Veillardc0826a72004-08-10 14:17:33 +000011799
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011800 if (ctxt->nberrors != 0) {
11801 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011802 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011803 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011804 return (ret);
11805}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011806
Daniel Veillard4255d502002-04-16 15:50:10 +000011807/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000011808 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000011809 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000011810 * @err: the error callback
11811 * @warn: the warning callback
11812 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000011813 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011814 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011815 */
11816void
11817xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011818 xmlSchemaValidityErrorFunc err,
11819 xmlSchemaValidityWarningFunc warn, void *ctx)
11820{
Daniel Veillard4255d502002-04-16 15:50:10 +000011821 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011822 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011823 ctxt->error = err;
11824 ctxt->warning = warn;
11825 ctxt->userData = ctx;
11826}
11827
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011828/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000011829 * xmlSchemaGetParserErrors:
11830 * @ctxt: a XMl-Schema parser context
11831 * @err: the error callback result
11832 * @warn: the warning callback result
11833 * @ctx: contextual data for the callbacks result
11834 *
11835 * Get the callback information used to handle errors for a parser context
11836 *
11837 * Returns -1 in case of failure, 0 otherwise
11838 */
11839int
11840xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
11841 xmlSchemaValidityErrorFunc * err,
11842 xmlSchemaValidityWarningFunc * warn, void **ctx)
11843{
11844 if (ctxt == NULL)
11845 return(-1);
11846 if (err != NULL)
11847 *err = ctxt->error;
11848 if (warn != NULL)
11849 *warn = ctxt->warning;
11850 if (ctx != NULL)
11851 *ctx = ctxt->userData;
11852 return(0);
11853}
11854
11855/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011856 * xmlSchemaFacetTypeToString:
11857 * @type: the facet type
11858 *
11859 * Convert the xmlSchemaTypeType to a char string.
11860 *
11861 * Returns the char string representation of the facet type if the
11862 * type is a facet and an "Internal Error" string otherwise.
11863 */
11864static const char *
11865xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
11866{
11867 switch (type) {
11868 case XML_SCHEMA_FACET_PATTERN:
11869 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011870 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011871 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011872 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011873 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011874 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011875 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011876 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011877 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011878 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011879 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011880 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011881 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011882 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011883 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011884 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011885 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011886 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011887 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011888 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011889 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011890 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011891 return ("fractionDigits");
11892 default:
11893 break;
11894 }
11895 return ("Internal Error");
11896}
11897
Daniel Veillardc0826a72004-08-10 14:17:33 +000011898static xmlChar *
11899xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
11900 const xmlChar *cur = value;
11901 xmlChar *ret = NULL, *mcur;
11902
11903 if (value == NULL)
11904 return(NULL);
11905
11906 while ((*cur != 0) &&
11907 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
11908 cur++;
11909 }
11910 if (*cur == 0)
11911 return (NULL);
11912 ret = xmlStrdup(value);
11913 /* TODO FIXME: I guess gcc will bark at this. */
11914 mcur = (xmlChar *) (ret + (cur - value));
11915 do {
11916 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
11917 *mcur = ' ';
11918 mcur++;
11919 } while (*mcur != 0);
11920 return(ret);
11921}
11922
11923static int
11924xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
11925{
11926 xmlSchemaTypePtr anc;
11927
11928 /*
11929 * The normalization type can be changed only for types which are derived
11930 * from xsd:string.
11931 */
11932 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11933 if ((type->builtInType == XML_SCHEMAS_STRING) &&
11934 (type->builtInType == XML_SCHEMAS_NORMSTRING))
11935
11936 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11937 else {
11938 /*
11939 * For all ·atomic· datatypes other than string (and types ·derived·
11940 * by ·restriction· from it) the value of whiteSpace is fixed to
11941 * collapse
11942 */
11943 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11944 }
11945 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11946 /*
11947 * For list types the facet "whiteSpace" is fixed to "collapse".
11948 */
11949 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11950 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11951 return (-1);
11952 } else if (type->facetSet != NULL) {
11953 xmlSchemaTypePtr anyST;
11954 xmlSchemaFacetLinkPtr lin;
11955
11956 /*
11957 * Atomic types.
11958 */
11959 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11960 anc = type->baseType;
11961 do {
11962 /*
11963 * For all ·atomic· datatypes other than string (and types ·derived·
11964 * by ·restriction· from it) the value of whiteSpace is fixed to
11965 * collapse
11966 */
11967 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
11968 (anc->builtInType == XML_SCHEMAS_STRING)) {
11969
11970 lin = type->facetSet;
11971 do {
11972 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
11973 if (lin->facet->whitespace ==
11974 XML_SCHEMAS_FACET_COLLAPSE) {
11975 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11976 } else if (lin->facet->whitespace ==
11977 XML_SCHEMAS_FACET_REPLACE) {
11978 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
11979 } else
11980 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11981 break;
11982 }
11983 lin = lin->next;
11984 } while (lin != NULL);
11985 break;
11986 }
11987 anc = anc->baseType;
11988 } while (anc != anyST);
11989 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11990 }
11991 return (-1);
11992}
11993
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011994/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000011995 * xmlSchemaValidateFacetsInternal:
11996 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000011997 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000011998 * @facets: the list of facets to check
11999 * @value: the lexical repr of the value to validate
12000 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000012001 * @fireErrors: if 0, only internal errors will be fired;
12002 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000012003 *
12004 * Check a value against all facet conditions
12005 *
12006 * Returns 0 if the element is schemas valid, a positive error code
12007 * number otherwise and -1 in case of internal or API error.
12008 */
12009static int
12010xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012011 xmlSchemaTypePtr type,
12012 const xmlChar * value,
12013 unsigned long length,
12014 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012015{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012016 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012017 xmlSchemaTypePtr biType; /* The build-in type. */
12018 xmlSchemaTypePtr tmpType;
12019 xmlSchemaFacetLinkPtr facetLink;
12020 int retFacet, hasFacet;
12021 xmlSchemaFacetPtr facet;
12022 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012023
Daniel Veillardc0826a72004-08-10 14:17:33 +000012024#ifdef DEBUG_UNION_VALIDATION
12025 printf("Facets of type: '%s'\n", (const char *) type->name);
12026 printf(" fireErrors: %d\n", fireErrors);
12027#endif
12028
12029 /*
12030 * NOTE: Do not jump away, if the facetSet of the given type is
12031 * empty: until now, "pattern" facets of the *base types* need to
12032 * be checked as well.
12033 */
12034 biType = type->baseType;
12035 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12036 biType = biType->baseType;
12037 if (biType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012038 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012039 "Internal error: xmlSchemaValidateFacetsInternal, "
12040 "the base type axis of the given type '%s' does not resolve to "
12041 "a built-in type.\n",
12042 type->name, NULL);
12043 return (-1);
12044 }
12045
12046 if (type->facetSet != NULL) {
12047 facetLink = type->facetSet;
12048 while (facetLink != NULL) {
12049 facet = facetLink->facet;
12050 /*
12051 * Skip the pattern "whiteSpace": it is used to
12052 * format the character content beforehand.
12053 */
12054 switch (facet->type) {
12055 case XML_SCHEMA_FACET_WHITESPACE:
12056 case XML_SCHEMA_FACET_PATTERN:
12057 case XML_SCHEMA_FACET_ENUMERATION:
12058 break;
12059 case XML_SCHEMA_FACET_LENGTH:
12060 case XML_SCHEMA_FACET_MINLENGTH:
12061 case XML_SCHEMA_FACET_MAXLENGTH:
12062 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12063 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12064 value, length, 0);
12065 len = length;
12066 } else
12067 ret = xmlSchemaValidateLengthFacet(biType, facet,
12068 value, ctxt->value, &len);
12069 break;
12070 default:
12071 ret = xmlSchemaValidateFacet(biType, facet, value,
12072 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012073 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012074 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012075 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012076 "Internal error: xmlSchemaValidateFacetsInternal, "
12077 "validating facet of type '%s'.\n",
12078 type->name, NULL);
12079 break;
12080 } else if ((ret > 0) && (fireErrors)) {
12081 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, len,
12082 type, facet, NULL, NULL, NULL, NULL);
12083 }
12084
12085 facetLink = facetLink->next;
12086 }
12087 if (ret >= 0) {
12088 /*
12089 * Process enumerations.
12090 */
12091 retFacet = 0;
12092 facetLink = type->facetSet;
12093 while (facetLink != NULL) {
12094 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12095 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12096 value, ctxt->value);
12097 if (retFacet <= 0)
12098 break;
12099 }
12100 facetLink = facetLink->next;
12101 }
12102 if (retFacet > 0) {
12103 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12104 if (fireErrors)
12105 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur,
12106 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12107 } else if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012108 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012109 "Internal error: xmlSchemaValidateFacetsInternal, "
12110 "validating facet of type '%s'.\n",
12111 BAD_CAST "enumeration", NULL);
12112 ret = -1;
12113 }
12114 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012115 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012116 if (ret >= 0) {
12117 /*
12118 * Process patters. Pattern facets are ORed at type level
12119 * and ANDed if derived. Walk the base type axis.
12120 */
12121 hasFacet = 0;
12122 tmpType = type;
12123 facet = NULL;
12124 do {
12125 retFacet = 0;
12126 for (facetLink = tmpType->facetSet; facetLink != NULL;
12127 facetLink = facetLink->next) {
12128 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
12129 continue;
12130 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12131 value, ctxt->value);
12132 if (retFacet <= 0)
12133 break;
12134 else
12135 /* Save the last non-validating facet. */
12136 facet = facetLink->facet;
12137 }
12138 if (retFacet != 0)
12139 break;
12140 tmpType = tmpType->baseType;
12141 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
12142 if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012143 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012144 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12145 "validating 'pattern' facets of type '%s'.\n",
12146 tmpType->name, NULL);
12147 ret = -1;
12148 } else if (retFacet > 0) {
12149 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
12150 if (fireErrors) {
12151 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, 0, type, facet,
12152 NULL, NULL, NULL, NULL);
12153 }
12154 }
12155 }
12156
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012157 return (ret);
12158}
12159
Daniel Veillard4255d502002-04-16 15:50:10 +000012160/************************************************************************
12161 * *
12162 * Simple type validation *
12163 * *
12164 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000012165
Daniel Veillard4255d502002-04-16 15:50:10 +000012166
12167/************************************************************************
12168 * *
12169 * DOM Validation code *
12170 * *
12171 ************************************************************************/
12172
12173static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012174 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012175static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012176 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000012177 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012178static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012179 xmlNodePtr elem,
12180 xmlSchemaElementPtr elemDecl,
12181 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012182
Daniel Veillard3646d642004-06-02 19:19:14 +000012183
12184/**
12185 * xmlSchemaFreeAttrStates:
12186 * @state: a list of attribute states
12187 *
12188 * Free the given list of attribute states
12189 *
12190 */
12191static void
12192xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
12193{
12194 xmlSchemaAttrStatePtr tmp;
12195 while (state != NULL) {
12196 tmp = state;
12197 state = state->next;
12198 xmlFree(tmp);
12199 }
12200}
12201
Daniel Veillard4255d502002-04-16 15:50:10 +000012202/**
12203 * xmlSchemaRegisterAttributes:
12204 * @ctxt: a schema validation context
12205 * @attrs: a list of attributes
12206 *
12207 * Register the list of attributes as the set to be validated on that element
12208 *
12209 * Returns -1 in case of error, 0 otherwise
12210 */
12211static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012212xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
12213{
Daniel Veillard3646d642004-06-02 19:19:14 +000012214 xmlSchemaAttrStatePtr tmp;
12215
12216 ctxt->attr = NULL;
12217 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012218 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012219 if ((attrs->ns != NULL) &&
12220 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
12221 attrs = attrs->next;
12222 continue;
12223 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012224 tmp = (xmlSchemaAttrStatePtr)
12225 xmlMalloc(sizeof(xmlSchemaAttrState));
12226 if (tmp == NULL) {
12227 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
12228 return (-1);
12229 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012230 tmp->attr = attrs;
12231 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
12232 tmp->next = NULL;
12233 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012234 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012235 else
12236 ctxt->attrTop->next = tmp;
12237 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012238 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012239 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012240 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012241}
12242
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012243#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000012244/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012245 * xmlSchemaValidateCheckNodeList
12246 * @nodelist: the list of nodes
12247 *
12248 * Check the node list is only made of text nodes and entities pointing
12249 * to text nodes
12250 *
12251 * Returns 1 if true, 0 if false and -1 in case of error
12252 */
12253static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012254xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
12255{
Daniel Veillard4255d502002-04-16 15:50:10 +000012256 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012257 if (nodelist->type == XML_ENTITY_REF_NODE) {
12258 TODO /* implement recursion in the entity content */
12259 }
12260 if ((nodelist->type != XML_TEXT_NODE) &&
12261 (nodelist->type != XML_COMMENT_NODE) &&
12262 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000012263 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012264 return (0);
12265 }
12266 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012267 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012268 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012269}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012270#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012271
12272/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012273 * xmlSchemaValidateCallback:
12274 * @ctxt: a schema validation context
12275 * @name: the name of the element detected (might be NULL)
12276 * @type: the type
12277 *
12278 * A transition has been made in the automata associated to an element
12279 * content model
12280 */
12281static void
12282xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012283 const xmlChar * name ATTRIBUTE_UNUSED,
12284 xmlSchemaTypePtr type, xmlNodePtr node)
12285{
Daniel Veillard4255d502002-04-16 15:50:10 +000012286 xmlSchemaTypePtr oldtype = ctxt->type;
12287 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012288
Daniel Veillard4255d502002-04-16 15:50:10 +000012289#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000012290 xmlGenericError(xmlGenericErrorContext,
12291 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012292 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012293#endif
12294 ctxt->type = type;
12295 ctxt->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012296 xmlSchemaValidateContent(ctxt, node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012297 ctxt->type = oldtype;
12298 ctxt->node = oldnode;
12299}
12300
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301/**
12302 * xmlSchemaValidateSimpleTypeValue:
12303 * @ctxt: a schema validation context
12304 * @value: the value to be validated
12305 * @fireErrors: shall errors be reported?
12306 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000012307 * @normalize: shall the value be normalized?
Daniel Veillard01fa6152004-06-29 17:04:39 +000012308 *
12309 * Validates a value by the given type (user derived or built-in).
12310 *
12311 * Returns 0 if the value is valid, a positive error code
12312 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012313 */
12314static int
12315xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
12316 const xmlChar *value,
12317 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012318 int applyFacets,
12319 int normalize)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012320{
12321 xmlSchemaTypePtr type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012322 int ret = 0;
12323 xmlChar *normValue = NULL;
12324 int wtsp;
12325
12326 type = ctxt->type;
12327 wtsp = ctxt->valueWS;
12328 /*
12329 * Normalize the value.
12330 */
12331 if (normalize &&
12332 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
12333 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
12334
12335 if ((norm != -1) && (norm > ctxt->valueWS)) {
12336 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12337 normValue = xmlSchemaCollapseString(value);
12338 else
12339 normValue = xmlSchemaWhiteSpaceReplace(value);
12340 ctxt->valueWS = norm;
12341 if (normValue != NULL)
12342 value = (const xmlChar *) normValue;
12343 }
12344 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012345 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
12346 xmlSchemaTypePtr base, anyType;
12347
12348 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12349
12350 base = type->baseType;
12351 while ((base != NULL) &&
12352 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
12353 (base->type != XML_SCHEMA_TYPE_BASIC) &&
12354 (base != anyType)) {
12355 base = base->baseType;
12356 }
12357 ctxt->type = base;
12358 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 0, 1);
12359 ctxt->type = type;
12360 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012361 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012362 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12363 "validating complex type '%s'\n",
12364 type->name, NULL);
12365 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12366 /*
12367 * Check facets.
12368 */
12369 /*
12370 * This is somehow not nice, since if an error occurs
12371 * the reported type will be the complex type; the spec
12372 * wants a simple type to be created on the complex type
12373 * if it has a simple content. For now we have to live with
12374 * it.
12375 */
12376 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12377 value, 0, fireErrors);
12378 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012379 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012380 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12381 "validating facets of complex type '%s'\n",
12382 type->name, NULL);
12383 } else if (ret > 0) {
12384 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
12385 /*
12386 Disabled, since the facet validation already reports errors.
12387 if (fireErrors)
12388 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12389 */
12390 }
12391 }
12392 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012393 xmlNodePtr child;
12394
12395 if (ctxt->value != NULL) {
12396 xmlSchemaFreeValue(ctxt->value);
12397 ctxt->value = NULL;
12398 }
12399 child = ctxt->node;
12400 while (child != NULL) {
12401 switch (child->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012402 case XML_TEXT_NODE:
12403 case XML_CDATA_SECTION_NODE:
12404 case XML_PI_NODE:
12405 case XML_COMMENT_NODE:
12406 case XML_XINCLUDE_START:
12407 case XML_XINCLUDE_END:
12408 break;
12409 case XML_ENTITY_REF_NODE:
12410 case XML_ENTITY_NODE:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012411 /* TODO: Scour the entities for illegal nodes. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012412 TODO break;
12413 case XML_ELEMENT_NODE: {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012414 /* NOTE: Changed to an internal error, since the
12415 * existence of an element node will be already checked in
12416 * xmlSchemaValidateSimpleTypeElement and in
12417 * xmlSchemaValidateComplexType.
12418 */
12419 xmlSchemaVCustomErr(ctxt,
12420 XML_SCHEMAV_INTERNAL,
12421 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12422 ctxt->cur, type,
12423 "Element found in content", NULL);
12424 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012425 }
12426 case XML_ATTRIBUTE_NODE:
12427 case XML_DOCUMENT_NODE:
12428 case XML_DOCUMENT_TYPE_NODE:
12429 case XML_DOCUMENT_FRAG_NODE:
12430 case XML_NOTATION_NODE:
12431 case XML_HTML_DOCUMENT_NODE:
12432 case XML_DTD_NODE:
12433 case XML_ELEMENT_DECL:
12434 case XML_ATTRIBUTE_DECL:
12435 case XML_ENTITY_DECL:
12436 case XML_NAMESPACE_DECL:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012437#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardc0826a72004-08-10 14:17:33 +000012438 case XML_DOCB_DOCUMENT_NODE:
12439#endif
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012440 {
12441 xmlSchemaVCustomErr(ctxt,
12442 XML_SCHEMAV_INTERNAL,
12443 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12444 ctxt->cur, NULL,
12445 "Node of unexpected type found in content",
12446 NULL);
12447 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012448 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012449 }
12450 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012451
12452 }
12453 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), ctxt->cur);
12454 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012455 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
12456 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
12457 else
12458 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012459 if (fireErrors)
12460 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012461 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012462 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012463 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012464 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012465 }
12466 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12467 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
12468 * a literal in the ·lexical space· of {base type definition}
12469 */
12470 ctxt->type = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012471 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0, 0);
12472 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012473 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012474 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012475 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012476 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012477 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012478 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012479 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012480 if (fireErrors)
12481 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12482 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012483 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012484 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012485 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012486 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12487 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012488 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012489 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012491 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012492 type->name, NULL);
12493 } else if (ret > 0) {
12494 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012495 /*
12496 Disabled, since the facet validation already reports errors.
12497 if (fireErrors)
12498 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12499 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012500 }
12501 }
12502 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12503
12504 xmlSchemaTypePtr tmpType;
12505 const xmlChar *cur, *end;
12506 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012507 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012508
12509 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
12510 * of white space separated tokens, each of which ·match·es a literal
12511 * in the ·lexical space· of {item type definition}
12512 */
12513
Daniel Veillardc0826a72004-08-10 14:17:33 +000012514 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012515 cur = value;
12516 do {
12517 while (IS_BLANK_CH(*cur))
12518 cur++;
12519 end = cur;
12520 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
12521 end++;
12522 if (end == cur)
12523 break;
12524 tmp = xmlStrndup(cur, end - cur);
12525 len++;
12526 ctxt->type = tmpType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012527 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1, 0);
12528 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012529 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012530 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012531 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012532 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12533 "validating an item of list simple type '%s'\n",
12534 type->name, NULL);
12535 break;
12536 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012537 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012538 if (fireErrors)
12539 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012540 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012542 cur = end;
12543 } while (*cur != 0);
12544 /*
12545 * Check facets.
12546 */
12547 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012548 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012549 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012550 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012551 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012552 } else if ((ret == 0) && (applyFacets)) {
12553 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12554 value, len, fireErrors);
12555 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012556 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012557 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12558 "validating facets of list simple type '%s'\n",
12559 type->name, NULL);
12560 } else if (ret > 0) {
12561 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012562 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012563 Disabled, since the facet validation already reports errors.
12564 if (fireErrors)
12565 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012566 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012567 }
12568
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 }
12570 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12571 xmlSchemaTypeLinkPtr memberLink;
12572
12573 /*
12574 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
12575 * not apply directly; however, the normalization behavior of ·union·
12576 * types is controlled by the value of whiteSpace on that one of the
12577 * ·memberTypes· against which the ·union· is successfully validated.
12578 *
12579 * This means that the value is normalized by the first validating
12580 * member type, then the facets of the union type are applied. This
12581 * needs changing of the value!
12582 */
12583
12584 /*
12585 * 1.2.3 if {variety} is ·union· then the string must ·match· a
12586 * literal in the ·lexical space· of at least one member of
12587 * {member type definitions}
12588 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012589#ifdef DEBUG_UNION_VALIDATION
12590 printf("Union ST : '%s'\n", (const char *) type->name);
12591 printf(" fireErrors : %d\n", fireErrors);
12592 printf(" applyFacets: %d\n", applyFacets);
12593#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000012594 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
12595 if (memberLink == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012596 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012597 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012598 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012599 type->name, NULL);
12600 ret = -1;
12601 }
12602 if (ret == 0) {
12603 while (memberLink != NULL) {
12604 ctxt->type = memberLink->type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012605 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012606 if ((ret <= 0) || (ret == 0))
12607 break;
12608 memberLink = memberLink->next;
12609 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012610 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012611 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012612 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012613 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012614 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012615 type->name, NULL);
12616 } else if (ret > 0) {
12617 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012618 if (fireErrors)
12619 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12620 }
12621 }
12622 /*
12623 * Apply facets (pattern, enumeration).
12624 */
12625 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12626 int mws;
12627 /*
12628 * The normalization behavior of ·union· types is controlled by
12629 * the value of whiteSpace on that one of the ·memberTypes·
12630 * against which the ·union· is successfully validated.
12631 */
12632 if (normValue != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012633 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012634 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12635 "the value was already normalized for the union simple "
12636 "type '%s'.\n", type->name, NULL);
12637 }
12638 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
12639 if (mws > ctxt->valueWS) {
12640 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12641 normValue = xmlSchemaCollapseString(value);
12642 else
12643 normValue = xmlSchemaWhiteSpaceReplace(value);
12644 if (normValue != NULL)
12645 value = (const xmlChar *) normValue;
12646 }
12647
12648 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12649 value, 0, fireErrors);
12650 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012651 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012652 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12653 "validating facets of union simple type '%s'\n",
12654 type->name, NULL);
12655 } else if (ret > 0) {
12656 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
12657 /*
12658 if (fireErrors)
12659 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12660 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012661 }
12662 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012663 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012664 ctxt->type = type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012665 ctxt->valueWS = wtsp;
12666 if (normValue != NULL)
12667 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012668 return (ret);
12669}
12670
12671/**
12672 * xmlSchemaValidateSimpleTypeElement:
12673 * @ctxt: a schema validation context
12674 * @node: the element node to be validated.
12675 *
12676 * Validate the element against a simple type.
12677 *
12678 * Returns 0 if the element is valid, a positive error code
12679 * number otherwise and -1 in case of an internal or API error.
12680 */
12681static int
12682xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12683{
12684 xmlNodePtr child;
12685 xmlSchemaTypePtr type;
12686 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012687 int ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012688 xmlChar *value;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012689 xmlNodePtr cur;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012690
12691
12692 child = ctxt->node;
12693 type = ctxt->type;
12694
12695 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012696 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012697 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
12698 node->name, NULL);
12699 return (-1);
12700 }
12701
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012702 /*
12703 * cvc-type: 3.1.2 The element information item must have no element
12704 * information item [children].
12705 */
12706 cur = child;
12707 while (cur != NULL) {
12708 if (cur->type == XML_ELEMENT_NODE) {
12709 xmlSchemaVCustomErr(ctxt,
12710 XML_SCHEMAV_CVC_TYPE_3_1_2,
12711 node, type,
12712 "No element content allowed", NULL);
12713 return (XML_SCHEMAV_CVC_TYPE_3_1_2);
12714 }
12715 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012716 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012717
Daniel Veillard01fa6152004-06-29 17:04:39 +000012718 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012719 * cvc-type 3.1.1:
12720 *
12721 * The attributes of must be empty, excepting those whose namespace name
12722 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
12723 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
12724 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012725 attr = node->properties;
12726 while (attr != NULL) {
12727 if ((attr->ns == NULL) ||
12728 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
12729 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
12730 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
12731 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
12732 (!xmlStrEqual
12733 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012734 xmlSchemaVIllegalAttrErr(ctxt,
12735 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012736 return (ctxt->err);
12737 }
12738 attr = attr->next;
12739 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012740 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
12741 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
12742 value = xmlNodeGetContent(child);
12743 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
12744 if (value != NULL)
12745 xmlFree(value);
12746 ctxt->type = type;
12747 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012748 return (ret);
12749}
Daniel Veillard4255d502002-04-16 15:50:10 +000012750
12751/**
12752 * xmlSchemaValidateElementType:
12753 * @ctxt: a schema validation context
12754 * @node: the top node.
12755 *
12756 * Validate the content of an element type.
12757 * Validation Rule: Element Locally Valid (Complex Type)
12758 *
12759 * Returns 0 if the element is schemas valid, a positive error code
12760 * number otherwise and -1 in case of internal or API error.
12761 */
12762static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012763xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12764{
Daniel Veillard4255d502002-04-16 15:50:10 +000012765 xmlNodePtr child;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012766 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000012767 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000012768 int ret;
12769 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
12770
Daniel Veillard01fa6152004-06-29 17:04:39 +000012771 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000012772 /*
12773 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
12774 * go in here as well.
12775 */
12776
12777 /* TODO: Is this one called always with an element declaration as the
12778 * context's type?
12779 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012780
12781 oldregexp = ctxt->regexp;
12782
12783 child = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012784 decl = (xmlSchemaElementPtr) ctxt->type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012785
Daniel Veillardc0826a72004-08-10 14:17:33 +000012786 if ((ctxt == NULL) || (decl == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012787 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000012788 "Internal error: xmlSchemaValidateElementType\n",
12789 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012790 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012791 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012792 /*
12793 * TODO: Since this should be already checked by the content model automaton,
12794 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
12795 * has been changed to XML_SCHEMAV_INTERNAL.
12796 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012797 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012798 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012799 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
12800 /* XML_SCHEMAS_ERR_MISSING, */
12801 "Element %s: missing child %s\n",
12802 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 }
12804 return (ctxt->err);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012805 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012806
12807 /*
12808 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012809 * TODO, FIXME: Can this still happen here? Isn't this already checked
12810 * by the content model automaton?
12811 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012812 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012813 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
12814 /* XML_SCHEMAS_ERR_WRONGELEM, */
12815 "Element %s: missing child %s found %s\n",
12816 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012817 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012818 }
12819 /*
12820 * Verify the attributes
12821 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012822 /*
12823 * TODO: This "attrTop" thing is not needed any more.
12824 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012825 attrs = ctxt->attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012826 attrTop = ctxt->attrTop;
12827 xmlSchemaRegisterAttributes(ctxt, child->properties);
12828 xmlSchemaValidateAttributes(ctxt, child, decl->subtypes);
12829 if (ctxt->attr != NULL)
12830 xmlSchemaFreeAttributeStates(ctxt->attr);
12831 ctxt->attr = attrs;
12832 ctxt->attrTop = attrTop;
Daniel Veillard3646d642004-06-02 19:19:14 +000012833
Daniel Veillard4255d502002-04-16 15:50:10 +000012834 /*
12835 * Verify the element content recursively
Daniel Veillardc0826a72004-08-10 14:17:33 +000012836 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012837 oldregexp = ctxt->regexp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012838 /*
12839 * FIXME TODO: This one creates a regexp even if no content
12840 * model was defined. Somehow ->contModel is always not NULL
12841 * for complex types, even if they are empty.
12842 */
12843 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012844 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
12845 (xmlRegExecCallbacks)
12846 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012847#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012848 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012849#endif
12850 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012851 xmlSchemaValidateType(ctxt, child, decl, decl->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000012852
12853 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012854 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012855#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012856 xmlGenericError(xmlGenericErrorContext,
12857 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000012858#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012859 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012860 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
12861 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012862 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012863 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
12864 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012865#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012866 } else {
12867 xmlGenericError(xmlGenericErrorContext,
12868 "Element %s content check succeeded\n",
12869 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012870
12871#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012872 }
12873 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000012874 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012875 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000012876 ctxt->node = child;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012877 ctxt->type = (xmlSchemaTypePtr) decl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012878 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012879}
12880
Daniel Veillard4255d502002-04-16 15:50:10 +000012881/**
Daniel Veillardc0826a72004-08-10 14:17:33 +000012882 * xmlSchemaValidateAnyInternal:
12883 * @ctxt: a schema validation context
12884 * @node: the top node.
12885 *
12886 * Represents the recursive portion of xmlSchemaValidateAny. Not
12887 * intended to be used by other functions.
12888 *
12889 * Returns 0 if the element is valid, a positive error code
12890 * number otherwise and -1 in case of an internal error.
12891 */
12892static int
12893xmlSchemaValidateAnyInternal(xmlSchemaValidCtxtPtr ctxt,
12894 xmlSchemaWildcardPtr wild,
12895 xmlNodePtr node)
12896{
12897 const xmlChar *uri;
12898 int ret = 0;
12899 xmlNodePtr child;
12900
12901 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
12902 xmlSchemaElementPtr decl = NULL;
12903
12904 if (node->ns != NULL)
12905 decl = xmlHashLookup3(ctxt->schema->elemDecl,
12906 node->name, node->ns->href, NULL);
12907 else
12908 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
12909 if (decl != NULL) {
12910 ctxt->node = node;
12911 ctxt->type = (xmlSchemaTypePtr) decl;
12912 ret = xmlSchemaValidateElementType(ctxt, node->parent);
12913 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012914 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012915 "Internal error: xmlSchemaValidateAnyInternal, "
12916 "validating an element in the context of a wildcard.",
12917 NULL, NULL);
12918 } else if (ret > 0)
12919 return (ret);
12920 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
12921 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012922 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
12923 node, wild, "Global declaration is absent");
Daniel Veillardc0826a72004-08-10 14:17:33 +000012924 return (ctxt->err);
12925 }
12926 }
12927 if (node->children != NULL) {
12928 child = node->children;
12929 do {
12930 if (child->type == XML_ELEMENT_NODE) {
12931 if (child->ns != NULL)
12932 uri = child->ns->href;
12933 else
12934 uri = NULL;
12935 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012936 /* TODO: error code. */
12937 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012938 child, wild,
12939 "The namespace of the element is not allowed.");
12940 return (ctxt->err);
12941 }
12942 ret = xmlSchemaValidateAnyInternal(ctxt, wild, child);
12943 if (ret != 0)
12944 return (ret);
12945 }
12946 child = child->next;
12947 } while (child != NULL);
12948 }
12949 return (0);
12950}
12951
12952/**
12953 * xmlSchemaValidateAny:
12954 * @ctxt: a schema validation context
12955 *
12956 * Returns 0 if the element is valid, a positive error code
12957 * number otherwise and -1 in case of an internal or API error.
12958 */
12959static int
12960xmlSchemaValidateAny(xmlSchemaValidCtxtPtr ctxt)
12961{
12962 return(xmlSchemaValidateAnyInternal(ctxt,
12963 ctxt->type->attributeWildcard, ctxt->cur));
12964}
12965
12966/**
William M. Brack2f2a6632004-08-20 23:09:47 +000012967 * xmlSchemaValidateAnyTypeContent:
12968 * @ctxt: a schema validation context
12969 * @node: the current element
12970 *
12971 * This one validates the content of an element of the type
12972 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
12973 * thus elements in the subtree will be validated, if a corresponding
12974 * declaration in the schema exists.
12975 *
12976 * Returns 0 if the element and its subtree is valid, a positive error code
12977 * otherwise and -1 in case of an internal or API error.
12978 */
12979static int
12980xmlSchemaValidateAnyTypeContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12981{
12982 xmlNodePtr top = node;
12983 xmlSchemaTypePtr decl;
12984 int skipContent, ret;
12985
12986 if (node->children == NULL)
12987 return (0);
12988 node = node->children;
12989 while (node != NULL) {
12990 skipContent = 0;
12991 if (node->type == XML_ELEMENT_NODE) {
12992 /*
12993 * The process contents of the wildcard is "lax", thus
12994 * we need to validate the element if a declaration
12995 * exists.
12996 */
12997 if (node->ns != NULL)
12998 decl = xmlHashLookup3(ctxt->schema->elemDecl,
12999 node->name, node->ns->href, NULL);
13000 else
13001 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13002
13003 if (decl != NULL) {
13004 ctxt->node = node;
13005 ctxt->type = (xmlSchemaTypePtr) decl;
13006 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13007 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013008 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013009 "Internal error: xmlSchemaValidateAnyTypeContent, "
13010 "validating an element in the context of a wildcard.",
13011 NULL, NULL);
13012 return (ret);
13013 } else if (ret > 0)
13014 return (ret);
13015 skipContent = 1;
13016 }
13017 }
13018 /*
13019 * Browse the full subtree, deep first.
13020 */
13021 if ((skipContent == 0) && (node->children != NULL)) {
13022 /* deep first */
13023 node = node->children;
13024 } else if ((node != top) && (node->next != NULL)) {
13025 /* then siblings */
13026 node = node->next;
13027 } else if (node != top) {
13028 /* go up to parents->next if needed */
13029 while (node != top) {
13030 if (node->parent != NULL)
13031 node = node->parent;
13032 if ((node != top) && (node->next != NULL)) {
13033 node = node->next;
13034 break;
13035 }
13036 if (node->parent == NULL) {
13037 node = NULL;
13038 break;
13039 }
13040 }
13041 /* exit condition */
13042 if (node == top)
13043 node = NULL;
13044 } else
13045 break;
13046 }
13047 return (0);
13048}
13049
13050/**
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013051 * xmlSchemaHasElemOrCharContent:
13052 * @node: the node
13053 *
13054 * Scours the content of the given node for element
13055 * and character nodes.
13056 *
13057 * Returns 1 if an element or character node is found,
13058 * 0 otherwise.
13059 */
13060static int
13061xmlSchemaHasElemOrCharContent(xmlNodePtr node)
13062{
13063 xmlNodePtr cur;
13064
13065 if (node == NULL)
13066 return (0);
13067 cur = node->children;
13068 while (cur != NULL) {
13069 if ((cur->type == XML_ELEMENT_NODE) ||
13070 /*
13071 * TODO: Ask Daniel if these are all character nodes.
13072 */
13073 (cur->type == XML_TEXT_NODE) ||
13074 (cur->type == XML_CDATA_SECTION_NODE) ||
13075 /*
13076 * TODO: How XML_ENTITY_NODEs evaluated?
13077 */
13078 (cur->type == XML_ENTITY_REF_NODE) ||
13079 (cur->type == XML_ENTITY_NODE)) {
13080 return (1);
13081 }
13082 cur = cur->next;
13083 }
13084 return (0);
13085}
13086
13087/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013088 * xmlSchemaValidateComplexType:
13089 * @ctxt: a schema validation context
13090 * @node: the top node.
13091 *
13092 * Validate the content of an element expected to be a complex type type
13093 * xmlschema-1.html#cvc-complex-type
13094 * Validation Rule: Element Locally Valid (Complex Type)
13095 *
13096 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000013097 * number otherwise and -1 in case of internal or API error.
13098 * Note on reported errors: Although it might be nice to report
13099 * the name of the simple/complex type, used to validate the content
13100 * of a node, it is quite unnecessary: for global defined types
13101 * the local name of the element is equal to the NCName of the type,
13102 * for local defined types it makes no sense to output the internal
13103 * computed name of the type. TODO: Instead, one should attach the
13104 * struct of the type involved to the error handler - this allows
13105 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000013106 */
13107static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013108xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13109{
Daniel Veillard4255d502002-04-16 15:50:10 +000013110 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013111 xmlSchemaTypePtr type;
13112 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000013113 const xmlChar *nsUri;
Daniel Veillard3646d642004-06-02 19:19:14 +000013114
Daniel Veillard4255d502002-04-16 15:50:10 +000013115 child = ctxt->node;
13116 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013117 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013118
Daniel Veillard4255d502002-04-16 15:50:10 +000013119 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120 case XML_SCHEMA_CONTENT_EMPTY: {
13121 /*
13122 * 1 If the {content type} is empty, then the element information
13123 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000013124 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013125 /*
13126 * TODO: Is the entity stuff correct?
13127 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013128 if (xmlSchemaHasElemOrCharContent(node) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013129 xmlSchemaVComplexTypeErr(ctxt,
13130 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
13131 node, type,
13132 "Character or element content is not allowed, "
13133 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013134 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013135 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013136 }
13137 case XML_SCHEMA_CONTENT_ELEMENTS:
13138 case XML_SCHEMA_CONTENT_MIXED:
13139 while (child != NULL) {
13140 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013141 if (child->ns != NULL)
13142 nsUri = child->ns->href;
13143 else
13144 nsUri = NULL;
13145 ret = xmlRegExecPushString2(ctxt->regexp,
13146 child->name, nsUri, child);
13147#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000013148 if (ret < 0)
13149 xmlGenericError(xmlGenericErrorContext,
13150 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000013151 else
13152 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013153 " --> %s\n", child->name);
13154#endif
13155 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
13156 /*
13157 * TODO: Ask Daniel if this are all character nodes.
13158 */
13159 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
13160 (child->type == XML_ENTITY_NODE) ||
13161 (child->type == XML_ENTITY_REF_NODE) ||
13162 (child->type == XML_CDATA_SECTION_NODE))) {
13163 /*
13164 * 2.3 If the {content type} is element-only, then the
13165 * element information item has no character information
13166 * item [children] other than those whose [character
13167 * code] is defined as a white space in [XML 1.0 (Second
13168 * Edition)].
13169 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013170 xmlSchemaVComplexTypeErr(ctxt,
13171 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
13172 node, type,
13173 "Character content is not allowed, "
13174 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013175 break;
13176 }
13177 child = child->next;
13178 }
13179 break;
13180 case XML_SCHEMA_CONTENT_SIMPLE:
13181 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013182 xmlChar *value = NULL;
13183 /*
13184 * We hit a complexType with a simpleContent resolving
13185 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000013186 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 /*
13188 * 2.2 If the {content type} is a simple type definition,
13189 * then the element information item has no element
13190 * information item [children], and the ·normalized value·
13191 * of the element information item is ·valid· with respect
13192 * to that simple type definition as defined by String
13193 * Valid (§3.14.4).
13194 */
13195 child = node->children;
13196 while (child != NULL) {
13197 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013198 xmlSchemaVComplexTypeErr(ctxt,
13199 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13200 node, type,
13201 "Element content is not allowed, because "
13202 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013203 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13204 break;
13205 }
13206 child = child->next;
13207 }
13208 if (ret == 0) {
13209 /*
13210 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000013211 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 if (ctxt->node == NULL)
13213 value = NULL;
13214 else
13215 value = xmlNodeGetContent(node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013216 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013217 if (ret > 0) {
13218 /*
13219 * NOTE: Although an error will be reported by
13220 * xmlSchemaValidateSimpleTypeValue, the spec wants
13221 * a specific complex type error to be reported
13222 * additionally.
13223 */
13224 xmlSchemaVComplexTypeErr(ctxt,
13225 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13226 node, type,
13227 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013228 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13229 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013230 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013231 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013232 "Element '%s': Error while validating character "
13233 "content against complex type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013234 node->name, type->name);
13235 return (-1);
13236 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013237 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013238 if (ret == 0) {
13239 /*
13240 * Apply facets of the complexType. Be sure to pass the
13241 * built-in type to xmlSchemaValidateFacetsInternal.
13242 */
13243 /* TODO: I don't know yet if the facets of the simple type
13244 * are used, or if the facets, defined by this complex type,
13245 * are to be used only. This here applies both facet sets.
13246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013247
13248 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13249 value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013251 xmlSchemaVComplexTypeErr(ctxt,
13252 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13253 node, type,
13254 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013255 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13256 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013257 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013258 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013259 "Element '%s': Error while validating character "
13260 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013261 "apply facets.\n",
13262 type->name, NULL);
13263 }
13264 }
13265 if (value != NULL)
13266 xmlFree(value);
13267 /* TODO: facets */
13268 break;
13269 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013270 default:
13271 TODO xmlGenericError(xmlGenericErrorContext,
13272 "unimplemented content type %d\n",
13273 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000013274 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013276 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013277}
13278
13279/**
13280 * xmlSchemaValidateContent:
13281 * @ctxt: a schema validation context
13282 * @elem: an element
13283 * @type: the type declaration
13284 *
13285 * Validate the content of an element against the type.
13286 *
13287 * Returns 0 if the element is schemas valid, a positive error code
13288 * number otherwise and -1 in case of internal or API error.
13289 */
13290static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013291xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13292{
Daniel Veillard4255d502002-04-16 15:50:10 +000013293 xmlSchemaTypePtr type;
13294
Daniel Veillard4255d502002-04-16 15:50:10 +000013295 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013296 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013297
13298 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013299 case XML_SCHEMA_TYPE_ANY:
Daniel Veillardc0826a72004-08-10 14:17:33 +000013300 xmlSchemaValidateAny(ctxt);
13301 ctxt->type = type;
13302 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013303 case XML_SCHEMA_TYPE_COMPLEX:
13304 xmlSchemaValidateComplexType(ctxt, node);
13305 break;
13306 case XML_SCHEMA_TYPE_ELEMENT:{
13307 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
13308
13309 /*
13310 * Handle element reference here
13311 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013312 /*
13313 * TODO: This should be removed, since checks for
13314 * consistence should not be done during validation.
13315 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013316 if (decl->ref != NULL) {
13317 if (decl->refDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013318 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013319 "Internal error: element reference %s "
13320 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013321 return (-1);
13322 }
13323 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
13324 decl = decl->refDecl;
13325 }
William M. Bracke7091952004-05-11 15:09:58 +000013326 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013327 xmlSchemaValidateElementType(ctxt, node);
13328 ctxt->type = type;
13329 break;
13330 }
13331 case XML_SCHEMA_TYPE_BASIC:
William M. Brack2f2a6632004-08-20 23:09:47 +000013332 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
13333 xmlSchemaValidateAnyTypeContent(ctxt, node);
13334 else
13335 xmlSchemaValidateSimpleTypeElement(ctxt, node);
13336 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013337 case XML_SCHEMA_TYPE_SIMPLE:
13338 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013339 break;
13340 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013341 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013342 case XML_SCHEMA_TYPE_SEQUENCE:
13343 TODO break;
13344 case XML_SCHEMA_TYPE_CHOICE:
13345 TODO break;
13346 case XML_SCHEMA_TYPE_ALL:
13347 TODO break;
13348 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13349 TODO break;
13350 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13351 TODO break;
13352 case XML_SCHEMA_TYPE_UR:
13353 TODO break;
13354 case XML_SCHEMA_TYPE_RESTRICTION:
13355 /*xmlSchemaValidateRestrictionType(ctxt, node); */
13356 TODO break;
13357 case XML_SCHEMA_TYPE_EXTENSION:
13358 TODO break;
13359 case XML_SCHEMA_TYPE_ATTRIBUTE:
13360 TODO break;
13361 case XML_SCHEMA_TYPE_GROUP:
13362 TODO break;
13363 case XML_SCHEMA_TYPE_NOTATION:
13364 TODO break;
13365 case XML_SCHEMA_TYPE_LIST:
13366 TODO break;
13367 case XML_SCHEMA_TYPE_UNION:
13368 TODO break;
13369 case XML_SCHEMA_FACET_MININCLUSIVE:
13370 TODO break;
13371 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13372 TODO break;
13373 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13374 TODO break;
13375 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13376 TODO break;
13377 case XML_SCHEMA_FACET_TOTALDIGITS:
13378 TODO break;
13379 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13380 TODO break;
13381 case XML_SCHEMA_FACET_PATTERN:
13382 TODO break;
13383 case XML_SCHEMA_FACET_ENUMERATION:
13384 TODO break;
13385 case XML_SCHEMA_FACET_WHITESPACE:
13386 TODO break;
13387 case XML_SCHEMA_FACET_LENGTH:
13388 TODO break;
13389 case XML_SCHEMA_FACET_MAXLENGTH:
13390 TODO break;
13391 case XML_SCHEMA_FACET_MINLENGTH:
13392 TODO break;
13393 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13394 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000013395 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
13396 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000013397 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013398
13399 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013400 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013401 ctxt->node = ctxt->node->next;
13402 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013403 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013404}
13405
13406/**
13407 * xmlSchemaValidateType:
13408 * @ctxt: a schema validation context
13409 * @elem: an element
13410 * @type: the list of type declarations
13411 *
13412 * Validate the content of an element against the types.
13413 *
13414 * Returns 0 if the element is schemas valid, a positive error code
13415 * number otherwise and -1 in case of internal or API error.
13416 */
13417static int
13418xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013419 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
13420{
Daniel Veillard4255d502002-04-16 15:50:10 +000013421 xmlChar *nil;
13422
Daniel Veillard2db8c122003-07-08 12:16:59 +000013423 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013424 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000013425
Daniel Veillard3646d642004-06-02 19:19:14 +000013426 /* This one is called by "xmlSchemaValidateElementType" and
13427 * "xmlSchemaValidateElement".
13428 */
13429
Daniel Veillard4255d502002-04-16 15:50:10 +000013430 /*
13431 * 3.3.4 : 2
13432 */
13433 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013434 xmlSchemaVCustomErr(ctxt,
13435 XML_SCHEMAV_CVC_ELT_2,
13436 elem, NULL,
13437 "The element declaration is abstract", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013438 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013439 }
13440 /*
13441 * 3.3.4: 3
13442 */
13443 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
13444 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013445 /* 3.3.4: 3.2 */
13446 if (xmlStrEqual(nil, BAD_CAST "true")) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013447 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
13448 xmlSchemaVCustomErr(ctxt,
13449 XML_SCHEMAV_CVC_ELT_3_2_1,
13450 /* XML_SCHEMAS_ERR_NOTEMPTY, */
13451 elem, NULL,
13452 "The 'nilled' element must have no character or element "
13453 "content", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013454 return (ctxt->err);
13455 }
13456 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
13457 (elemDecl->value != NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013458 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
13459 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
13460 elem, NULL,
13461 "There is a fixed value constraint defined for "
13462 "the 'nilled' element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013463 return (ctxt->err);
13464 }
13465 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013466 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013467 /* 3.3.4: 3.1 */
13468 if (nil != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013469 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_1,
13470 /* XML_SCHEMAS_ERR_NOTNILLABLE, */
13471 elem, NULL,
13472 "The element is not 'nillable'", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013473 xmlFree(nil);
13474 return (ctxt->err);
13475 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013476 }
13477
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013478 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000013479
13480 ctxt->type = elemDecl->subtypes;
13481 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013482 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013483 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013484}
13485
13486
13487/**
13488 * xmlSchemaValidateAttributes:
13489 * @ctxt: a schema validation context
13490 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000013491 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000013492 *
13493 * Validate the attributes of an element.
13494 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013495 * 1. Existent, invalid attributes are reported in the form
13496 * "prefix:localName".
13497 * Reason: readability - it is easier to find the actual XML
13498 * representation of the attributes QName.
13499 * 2. Missing attributes are reported in the form
13500 * {"URI", "localName"}.
13501 * This is necessary, since the the prefix need not to be declared
13502 * at all, and thus is not computable.
13503 *
Daniel Veillard4255d502002-04-16 15:50:10 +000013504 * Returns 0 if the element is schemas valid, a positive error code
13505 * number otherwise and -1 in case of internal or API error.
13506 */
13507static int
Daniel Veillard3646d642004-06-02 19:19:14 +000013508xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013509{
Daniel Veillard3646d642004-06-02 19:19:14 +000013510 int ret;
13511 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013512 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013513 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000013514 xmlSchemaAttributeLinkPtr attrUse;
13515 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013516 int found;
William M. Brack803812b2004-06-03 02:11:24 +000013517 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013518#ifdef DEBUG_ATTR_VALIDATION
13519 int redundant = 0;
13520#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013521
Daniel Veillardc0826a72004-08-10 14:17:33 +000013522 /*
13523 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
13524 * if we have an attribute reference or an attribute declaration.
13525 */
13526 /*
13527 * Allow all attributes if the type is anyType.
13528 */
13529 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
13530 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013531 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013532 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013533 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000013534 attrDecl = attrUse->attr;
13535#ifdef DEBUG_ATTR_VALIDATION
13536 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
13537 printf("attr use - use: %d\n", attrDecl->occurs);
13538#endif
13539 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
13540
13541 if (curState->decl == attrUse->attr) {
13542#ifdef DEBUG_ATTR_VALIDATION
13543 redundant = 1;
13544#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013545 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013546 attr = curState->attr;
13547#ifdef DEBUG_ATTR_VALIDATION
13548 printf("attr - name: %s\n", attr->name);
13549 if (attr->ns != NULL)
13550 printf("attr - ns: %s\n", attr->ns->href);
13551 else
13552 printf("attr - ns: none\n");
13553#endif
13554 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013555 if (attr == NULL)
13556 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013557 if (attrDecl->ref != NULL) {
13558 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013559 continue;
13560 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013561 if ((attrDecl->refNs == NULL) ||
13562 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013563 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013564 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013565 continue;
13566 }
13567 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013568 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013569 continue;
13570 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013571 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013572 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013573 if (attr->ns == NULL) {
13574 /*
William M. Bracke7091952004-05-11 15:09:58 +000013575 * accept an unqualified attribute only if the target
13576 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013577 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013578 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000013579 /*
13580 * This check was removed, since the target namespace
13581 * was evaluated during parsing and already took
13582 * "attributeFormDefault" into account.
13583 */
13584 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013585 continue;
13586 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013587 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013588 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013589 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013590 attr->ns->href))
13591 continue;
13592 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013593 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013594#ifdef DEBUG_ATTR_VALIDATION
13595 printf("found\n");
13596#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013597 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000013598 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013599 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013600
Daniel Veillard3646d642004-06-02 19:19:14 +000013601 if (attrDecl->subtypes == NULL) {
13602 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
13603 curState->decl = attrDecl;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013604 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013605 "Internal error: attribute %s type not resolved\n",
13606 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013607 continue;
13608 }
13609 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013610 ctxt->type = attrDecl->subtypes;
13611 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013612 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000013613 if (ret != 0)
13614 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13615 else
13616 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13617 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013618 if (value != NULL) {
13619 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000013620 }
13621 }
13622 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
13623 xmlSchemaAttrStatePtr tmp;
13624
13625#ifdef DEBUG_ATTR_VALIDATION
13626 printf("required attr not found\n");
13627#endif
13628 /*
13629 * Add a new dummy attribute state.
13630 */
13631 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
13632 if (tmp == NULL) {
13633 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
13634 return (-1);
13635 }
13636 tmp->attr = NULL;
13637 tmp->state = XML_SCHEMAS_ATTR_MISSING;
13638 tmp->decl = attrDecl;
13639 tmp->next = NULL;
13640
13641 if (reqAttrStates == NULL) {
13642 reqAttrStates = tmp;
13643 reqAttrStatesTop = tmp;
13644 } else {
13645 reqAttrStatesTop->next = tmp;
13646 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013647 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013648
13649 }
13650 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013651 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013652 /*
13653 * Add required attributes to the attribute states of the context.
13654 */
13655 if (reqAttrStates != NULL) {
13656 if (ctxt->attr == NULL) {
13657 ctxt->attr = reqAttrStates;
13658 } else {
13659 ctxt->attrTop->next = reqAttrStates;
13660 }
13661 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013662 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013663 /*
13664 * Process wildcards.
13665 */
13666 if (type->attributeWildcard != NULL) {
13667#ifdef DEBUG_ATTR_VALIDATION
13668 xmlSchemaWildcardNsPtr ns;
13669 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013670 if (type->attributeWildcard->processContents ==
13671 XML_SCHEMAS_ANY_LAX)
13672 printf("processContents: lax\n");
13673 else if (type->attributeWildcard->processContents ==
13674 XML_SCHEMAS_ANY_STRICT)
13675 printf("processContents: strict\n");
13676 else
13677 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000013678 if (type->attributeWildcard->any)
13679 printf("type: any\n");
13680 else if (type->attributeWildcard->negNsSet != NULL) {
13681 printf("type: negated\n");
13682 if (type->attributeWildcard->negNsSet->value == NULL)
13683 printf("ns: (absent)\n");
13684 else
13685 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
13686 } else if (type->attributeWildcard->nsSet != NULL) {
13687 printf("type: set\n");
13688 ns = type->attributeWildcard->nsSet;
13689 while (ns != NULL) {
13690 if (ns->value == NULL)
13691 printf("ns: (absent)\n");
13692 else
13693 printf("ns: %s\n", ns->value);
13694 ns = ns->next;
13695 }
13696 } else
13697 printf("empty\n");
13698
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013699
13700#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000013701 curState = ctxt->attr;
13702 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013703 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
13704 if (curState->attr->ns != NULL)
13705 nsURI = curState->attr->ns->href;
13706 else
13707 nsURI = NULL;
13708 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
13709 nsURI)) {
13710 /*
13711 * Handle processContents.
13712 */
13713 if ((type->attributeWildcard->processContents ==
13714 XML_SCHEMAS_ANY_LAX) ||
13715 (type->attributeWildcard->processContents ==
13716 XML_SCHEMAS_ANY_STRICT)) {
13717
13718 attr = curState->attr;
13719 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
13720 attr->name, nsURI);
13721 if (attrDecl != NULL) {
13722 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013723 ctxt->cur = (xmlNodePtr) attr;
13724 ctxt->node = attr->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 ctxt->type = attrDecl->subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013728 if (ret != 0)
13729 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13730 else
13731 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13732 curState->decl = attrDecl;
13733 if (value != NULL) {
13734 xmlFree(value);
13735 }
13736
13737 } else if (type->attributeWildcard->processContents ==
13738 XML_SCHEMAS_ANY_LAX) {
13739 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13740 }
13741 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000013742 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013743 }
13744 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013745 curState = curState->next;
13746 }
13747 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013748 /*
13749 * Report missing and illegal attributes.
13750 */
13751 if (ctxt->attr != NULL) {
13752 curState = ctxt->attr;
13753 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
13754 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
13755 attr = curState->attr;
13756 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
13757 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013758 else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
13759 /* TODO: "prohibited" won't ever be touched here!.
13760 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
13761 */
13762 if (type->attributeWildcard == NULL) {
13763 xmlSchemaVIllegalAttrErr(ctxt,
13764 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
13765 } else {
13766 xmlSchemaVIllegalAttrErr(ctxt,
13767 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
13768 }
13769 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013770 }
13771 curState = curState->next;
13772 }
13773 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013774#ifdef DEBUG_ATTR_VALIDATION
13775 if (redundant)
13776 xmlGenericError(xmlGenericErrorContext,
13777 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
13778 type->name);
13779#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013780 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013781}
13782
13783/**
13784 * xmlSchemaValidateElement:
13785 * @ctxt: a schema validation context
13786 * @elem: an element
13787 *
13788 * Validate an element in a tree
13789 *
13790 * Returns 0 if the element is schemas valid, a positive error code
13791 * number otherwise and -1 in case of internal or API error.
13792 */
13793static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013794xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
13795{
Daniel Veillard4255d502002-04-16 15:50:10 +000013796 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000013797 int ret;
13798 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013799
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013800 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013801 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13802 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013803 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013804 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13805 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013806 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013807 /*
13808 * This one is called by xmlSchemaValidateDocument and
13809 * xmlSchemaValidateAnyInernal.
13810 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013811
Daniel Veillard4255d502002-04-16 15:50:10 +000013812 /*
13813 * 3.3.4 : 1
13814 */
13815 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013816 xmlSchemaVCustomErr(ctxt,
13817 XML_SCHEMAV_CVC_ELT_1,
13818 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
13819 elem, NULL,
13820 "Global declaration is absent", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013821 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013822 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013823 /* TODO: This should be already catched at the schema parsing level. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013824 if (elemDecl->subtypes == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013825 xmlSchemaVCustomErr(ctxt,
13826 XML_SCHEMAV_INTERNAL,
13827 /* XML_SCHEMAS_ERR_NOTYPE */
13828 elem, NULL,
13829 "The element declaration has no type assigned", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013830 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013831 }
13832 /*
13833 * Verify the attributes
13834 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013835 attrs = ctxt->attr;
13836 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013837 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013838 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->subtypes);
13839 if (ctxt->attr != NULL)
13840 xmlSchemaFreeAttributeStates(ctxt->attr);
13841 ctxt->attr = attrs;
13842 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013843 /*
13844 * Verify the element content recursively
13845 */
13846 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013847 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
13848 (xmlRegExecCallbacks)
13849 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013850#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013851 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013852#endif
13853 }
13854 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013855 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013856 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013857#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013858 xmlGenericError(xmlGenericErrorContext,
13859 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013860#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000013861 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013862 /* TODO: error code. */
13863 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13864 elem, elemDecl->subtypes,
13865 "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013866 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013867 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13868 elem, elemDecl->subtypes,
13869 "The element content is not valid", NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013870#ifdef DEBUG_CONTENT
Daniel Veillardc0826a72004-08-10 14:17:33 +000013871 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013872 xmlGenericError(xmlGenericErrorContext,
13873 "Element %s content check succeeded\n",
13874 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013875
13876#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013877 }
13878 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000013879 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013880 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013881}
13882
13883/**
13884 * xmlSchemaValidateDocument:
13885 * @ctxt: a schema validation context
13886 * @doc: a parsed document tree
13887 *
13888 * Validate a document tree in memory.
13889 *
13890 * Returns 0 if the document is schemas valid, a positive error code
13891 * number otherwise and -1 in case of internal or API error.
13892 */
13893static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013894xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
13895{
Daniel Veillard4255d502002-04-16 15:50:10 +000013896 xmlNodePtr root;
13897 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013898
Daniel Veillard4255d502002-04-16 15:50:10 +000013899 root = xmlDocGetRootElement(doc);
13900 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013901 xmlSchemaVCustomErr(ctxt,
13902 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
13903 (xmlNodePtr) doc, NULL,
13904 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013905 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013906 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013907
Daniel Veillard4255d502002-04-16 15:50:10 +000013908 if (root->ns != NULL)
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013909 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, root->ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +000013910 else
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013911 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013912 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013913 xmlSchemaVCustomErr(ctxt,
13914 XML_SCHEMAV_CVC_ELT_1,
13915 root, NULL,
13916 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
13917 "Global declaration is absent", NULL);
13918 }
13919 /*
13920 * Removed, since xmlSchemaGetElem will return global declarations only.
13921 *
13922 else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000013923 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000013924 "Root element %s not global\n", root->name, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013925 }
13926 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013927 /*
13928 * Okay, start the recursive validation
13929 */
13930 xmlSchemaValidateElement(ctxt, root);
13931
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013932 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013933}
13934
13935/************************************************************************
13936 * *
13937 * SAX Validation code *
13938 * *
13939 ************************************************************************/
13940
13941/************************************************************************
13942 * *
13943 * Validation interfaces *
13944 * *
13945 ************************************************************************/
13946
13947/**
13948 * xmlSchemaNewValidCtxt:
13949 * @schema: a precompiled XML Schemas
13950 *
13951 * Create an XML Schemas validation context based on the given schema
13952 *
13953 * Returns the validation context or NULL in case of error
13954 */
13955xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013956xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
13957{
Daniel Veillard4255d502002-04-16 15:50:10 +000013958 xmlSchemaValidCtxtPtr ret;
13959
13960 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
13961 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013962 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013963 return (NULL);
13964 }
13965 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013966 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000013967 ret->attrTop = NULL;
13968 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013969 return (ret);
13970}
13971
13972/**
13973 * xmlSchemaFreeValidCtxt:
13974 * @ctxt: the schema validation context
13975 *
13976 * Free the resources associated to the schema validation context
13977 */
13978void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013979xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
13980{
Daniel Veillard4255d502002-04-16 15:50:10 +000013981 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013982 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013983 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013984 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000013985 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013986 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000013987 xmlFree(ctxt);
13988}
13989
13990/**
13991 * xmlSchemaSetValidErrors:
13992 * @ctxt: a schema validation context
13993 * @err: the error function
13994 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000013995 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000013996 *
William M. Brack2f2a6632004-08-20 23:09:47 +000013997 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000013998 */
13999void
14000xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014001 xmlSchemaValidityErrorFunc err,
14002 xmlSchemaValidityWarningFunc warn, void *ctx)
14003{
Daniel Veillard4255d502002-04-16 15:50:10 +000014004 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014005 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014006 ctxt->error = err;
14007 ctxt->warning = warn;
14008 ctxt->userData = ctx;
14009}
14010
14011/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014012 * xmlSchemaGetValidErrors:
14013 * @ctxt: a XML-Schema validation context
14014 * @err: the error function result
14015 * @warn: the warning function result
14016 * @ctx: the functions context result
14017 *
14018 * Get the error and warning callback informations
14019 *
14020 * Returns -1 in case of error and 0 otherwise
14021 */
14022int
14023xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
14024 xmlSchemaValidityErrorFunc * err,
14025 xmlSchemaValidityWarningFunc * warn, void **ctx)
14026{
14027 if (ctxt == NULL)
14028 return (-1);
14029 if (err != NULL)
14030 *err = ctxt->error;
14031 if (warn != NULL)
14032 *warn = ctxt->warning;
14033 if (ctx != NULL)
14034 *ctx = ctxt->userData;
14035 return (0);
14036}
14037
14038/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014039 * xmlSchemaValidateDoc:
14040 * @ctxt: a schema validation context
14041 * @doc: a parsed document tree
14042 *
14043 * Validate a document tree in memory.
14044 *
14045 * Returns 0 if the document is schemas valid, a positive error code
14046 * number otherwise and -1 in case of internal or API error.
14047 */
14048int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014049xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14050{
Daniel Veillard4255d502002-04-16 15:50:10 +000014051 int ret;
14052
14053 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014054 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014055
14056 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000014057 ctxt->err = 0;
14058 ctxt->nberrors = 0;
14059
Daniel Veillard4255d502002-04-16 15:50:10 +000014060 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014061 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000014062}
14063
14064/**
14065 * xmlSchemaValidateStream:
14066 * @ctxt: a schema validation context
14067 * @input: the input to use for reading the data
14068 * @enc: an optional encoding information
14069 * @sax: a SAX handler for the resulting events
14070 * @user_data: the context to provide to the SAX handler.
14071 *
14072 * Validate a document tree in memory.
14073 *
14074 * Returns 0 if the document is schemas valid, a positive error code
14075 * number otherwise and -1 in case of internal or API error.
14076 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014077int
Daniel Veillard4255d502002-04-16 15:50:10 +000014078xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014079 xmlParserInputBufferPtr input, xmlCharEncoding enc,
14080 xmlSAXHandlerPtr sax, void *user_data)
14081{
Daniel Veillard4255d502002-04-16 15:50:10 +000014082 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014083 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014084 ctxt->input = input;
14085 ctxt->enc = enc;
14086 ctxt->sax = sax;
14087 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014088 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014089}
14090
14091#endif /* LIBXML_SCHEMAS_ENABLED */