blob: 12cc8c134d4b6b3eb26e112bc995d9c425fb52ae [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;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003246 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003247
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003248 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003249 attr = xmlSchemaGetPropNode(node, name);
3250 if (attr == NULL)
3251 return (NULL);
3252 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3253 /*
3254 * TODO: Is the empty value valid for QNames?
3255 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003256 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003257 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003258
Daniel Veillardba0153a2004-04-01 10:42:31 +00003259 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003260 ns = xmlSearchNs(node->doc, node, 0);
3261 if (ns) {
3262 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3263 return (val);
3264 }
3265 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003266 ret = xmlSplitQName3(val, &len);
3267 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003269 }
3270 ret = xmlDictLookup(ctxt->dict, ret, -1);
3271 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003272
3273 ns = xmlSearchNs(node->doc, node, prefix);
3274 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003275 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3276 NULL, NULL, (xmlNodePtr) attr,
3277 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
3278 "The prefix '%s' of the QName value "
3279 "'%s' has no corresponding namespace declaration in scope",
3280 prefix, val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003281 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003282 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003283 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003284 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003285}
3286
3287/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003288 * xmlSchemaPValAttrNodeQNameValue:
3289 * @ctxt: a schema parser context
3290 * @schema: the schema context
3291 * @ownerDes: the designation of the parent element
3292 * @ownerItem: the parent as a schema object
3293 * @value: the QName value
3294 * @local: the resulting local part if found, the attribute value otherwise
3295 * @uri: the resulting namespace URI if found
3296 *
3297 * Extracts the local name and the URI of a QName value and validates it.
3298 * This one is intended to be used on attribute values that
3299 * should resolve to schema components.
3300 *
3301 * Returns 0, in case the QName is valid, a positive error code
3302 * if not valid and -1 if an internal error occurs.
3303 */
3304static int
3305xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3306 xmlSchemaPtr schema,
3307 xmlChar **ownerDes,
3308 xmlSchemaTypePtr ownerItem,
3309 xmlAttrPtr attr,
3310 const xmlChar *value,
3311 const xmlChar **uri,
3312 const xmlChar **prefix,
3313 const xmlChar **local)
3314{
3315 const xmlChar *pref;
3316 xmlNsPtr ns;
3317 int len, ret;
3318
3319 *uri = NULL;
3320 *local = NULL;
3321 if (prefix != 0)
3322 *prefix = NULL;
3323 ret = xmlValidateQName(value, 1);
3324 if (ret > 0) {
3325 xmlSchemaPSimpleTypeErr(ctxt,
3326 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3327 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003328 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3329 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003330 NULL, NULL, NULL);
3331 *local = value;
3332 return (ctxt->err);
3333 } else if (ret < 0)
3334 return (-1);
3335
3336 if (!strchr((char *) value, ':')) {
3337 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3338 if (ns)
3339 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3340 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3341 /*
3342 * This one takes care of included schemas with no
3343 * target namespace.
3344 */
3345 *uri = schema->targetNamespace;
3346 }
3347 *local = value;
3348 return (0);
3349 }
3350 /*
3351 * At this point xmlSplitQName3 has to return a local name.
3352 */
3353 *local = xmlSplitQName3(value, &len);
3354 *local = xmlDictLookup(ctxt->dict, *local, -1);
3355 pref = xmlDictLookup(ctxt->dict, value, len);
3356 if (prefix != 0)
3357 *prefix = pref;
3358 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3359 if (ns == NULL) {
3360 xmlSchemaPSimpleTypeErr(ctxt,
3361 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3362 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003363 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003364 "The prefix '%s' of the value '%s' is not declared.\n",
3365 pref, value);
3366 return (ctxt->err);
3367 } else {
3368 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3369 }
3370 return (0);
3371}
3372
3373/**
3374 * xmlSchemaPValAttrNodeQName:
3375 * @ctxt: a schema parser context
3376 * @schema: the schema context
3377 * @ownerDes: the designation of the owner element
3378 * @ownerItem: the owner as a schema object
3379 * @attr: the attribute node
3380 * @local: the resulting local part if found, the attribute value otherwise
3381 * @uri: the resulting namespace URI if found
3382 *
3383 * Extracts and validates the QName of an attribute value.
3384 * This one is intended to be used on attribute values that
3385 * should resolve to schema components.
3386 *
3387 * Returns 0, in case the QName is valid, a positive error code
3388 * if not valid and -1 if an internal error occurs.
3389 */
3390static int
3391xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3392 xmlSchemaPtr schema,
3393 xmlChar **ownerDes,
3394 xmlSchemaTypePtr ownerItem,
3395 xmlAttrPtr attr,
3396 const xmlChar **uri,
3397 const xmlChar **prefix,
3398 const xmlChar **local)
3399{
3400 const xmlChar *value;
3401
3402 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3403 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3404 ownerDes, ownerItem, attr, value, uri, prefix, local));
3405}
3406
3407/**
3408 * xmlSchemaPValAttrQName:
3409 * @ctxt: a schema parser context
3410 * @schema: the schema context
3411 * @ownerDes: the designation of the parent element
3412 * @ownerItem: the owner as a schema object
3413 * @ownerElem: the parent node of the attribute
3414 * @name: the name of the attribute
3415 * @local: the resulting local part if found, the attribute value otherwise
3416 * @uri: the resulting namespace URI if found
3417 *
3418 * Extracts and validates the QName of an attribute value.
3419 *
3420 * Returns 0, in case the QName is valid, a positive error code
3421 * if not valid and -1 if an internal error occurs.
3422 */
3423static int
3424xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3425 xmlSchemaPtr schema,
3426 xmlChar **ownerDes,
3427 xmlSchemaTypePtr ownerItem,
3428 xmlNodePtr ownerElem,
3429 const char *name,
3430 const xmlChar **uri,
3431 const xmlChar **prefix,
3432 const xmlChar **local)
3433{
3434 xmlAttrPtr attr;
3435
3436 attr = xmlSchemaGetPropNode(ownerElem, name);
3437 if (attr == NULL) {
3438 *local = NULL;
3439 *uri = NULL;
3440 return (0);
3441 }
3442 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3443 ownerDes, ownerItem, attr, uri, prefix, local));
3444}
3445
3446/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003447 * xmlGetMaxOccurs:
3448 * @ctxt: a schema validation context
3449 * @node: a subtree containing XML Schema informations
3450 *
3451 * Get the maxOccurs property
3452 *
3453 * Returns the default if not found, or the value
3454 */
3455static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003456xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3457 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003458{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003459 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003460 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003461 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003462
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003463 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3464 if (attr == NULL)
3465 return (def);
3466 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003467
3468 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003469 if (max != UNBOUNDED) {
3470 xmlSchemaPSimpleTypeErr(ctxt,
3471 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3472 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3473 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3474 val, NULL, NULL, NULL);
3475 return (def);
3476 } else
3477 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003478 }
3479
3480 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003481 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003482 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003483 if (*cur == 0) {
3484 xmlSchemaPSimpleTypeErr(ctxt,
3485 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3486 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3487 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3488 val, NULL, NULL, NULL);
3489 return (def);
3490 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003492 ret = ret * 10 + (*cur - '0');
3493 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 }
William M. Brack76e95df2003-10-18 16:20:14 +00003495 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003496 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003497 /*
3498 * TODO: Restrict the maximal value to Integer.
3499 */
3500 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3501 xmlSchemaPSimpleTypeErr(ctxt,
3502 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3503 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3504 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3505 val, NULL, NULL, NULL);
3506 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003508 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003509}
3510
3511/**
3512 * xmlGetMinOccurs:
3513 * @ctxt: a schema validation context
3514 * @node: a subtree containing XML Schema informations
3515 *
3516 * Get the minOccurs property
3517 *
3518 * Returns the default if not found, or the value
3519 */
3520static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003521xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3522 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003523{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003524 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003525 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003526 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003527
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003528 attr = xmlSchemaGetPropNode(node, "minOccurs");
3529 if (attr == NULL)
3530 return (def);
3531 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003532 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003533 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003534 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003535 if (*cur == 0) {
3536 xmlSchemaPSimpleTypeErr(ctxt,
3537 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3538 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3539 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3540 val, NULL, NULL, NULL);
3541 return (def);
3542 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003543 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003544 ret = ret * 10 + (*cur - '0');
3545 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 }
William M. Brack76e95df2003-10-18 16:20:14 +00003547 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003548 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003549 /*
3550 * TODO: Restrict the maximal value to Integer.
3551 */
3552 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3553 xmlSchemaPSimpleTypeErr(ctxt,
3554 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3555 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3556 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3557 val, NULL, NULL, NULL);
3558 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003559 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003560 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003561}
3562
3563/**
3564 * xmlGetBooleanProp:
3565 * @ctxt: a schema validation context
3566 * @node: a subtree containing XML Schema informations
3567 * @name: the attribute name
3568 * @def: the default value
3569 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003570 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003571 *
3572 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003573 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003574 */
3575static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003576xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3577 xmlChar **ownerDes,
3578 xmlSchemaTypePtr ownerItem,
3579 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003580 const char *name, int def)
3581{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003582 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003583
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003584 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003586 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003587 /*
3588 * 3.2.2.1 Lexical representation
3589 * An instance of a datatype that is defined as ·boolean·
3590 * can have the following legal literals {true, false, 1, 0}.
3591 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003592 if (xmlStrEqual(val, BAD_CAST "true"))
3593 def = 1;
3594 else if (xmlStrEqual(val, BAD_CAST "false"))
3595 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003596 else if (xmlStrEqual(val, BAD_CAST "1"))
3597 def = 1;
3598 else if (xmlStrEqual(val, BAD_CAST "0"))
3599 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003601 xmlSchemaPSimpleTypeErr(ctxt,
3602 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003603 ownerDes, ownerItem, node,
3604 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3605 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003606 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003607 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003608}
3609
3610/************************************************************************
3611 * *
3612 * Shema extraction from an Infoset *
3613 * *
3614 ************************************************************************/
3615static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3616 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003617 xmlNodePtr node,
3618 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003619static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3620 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003622 xmlNodePtr node,
3623 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003624static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3625 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003627 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003628static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3629 xmlSchemaPtr schema,
3630 xmlNodePtr node);
3631static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3632 xmlSchemaPtr schema,
3633 xmlNodePtr node);
3634static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3635 ctxt,
3636 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003637 xmlNodePtr node,
3638 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003639static xmlSchemaAttributeGroupPtr
3640xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003641 xmlSchemaPtr schema, xmlNodePtr node,
3642 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003643static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3644 xmlSchemaPtr schema,
3645 xmlNodePtr node);
3646static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3647 xmlSchemaPtr schema,
3648 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003649static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3651 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003652
3653/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003654 * xmlSchemaPValAttrNode:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003655 *
3656 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003657 * @ownerDes: the designation of the parent element
3658 * @ownerItem: the schema object owner if existent
3659 * @attr: the schema attribute node being validated
3660 * @value: the value
3661 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003662 *
3663 * Validates a value against the given built-in type.
3664 * This one is intended to be used internally for validation
3665 * of schema attribute values during parsing of the schema.
3666 *
3667 * Returns 0 if the value is valid, a positive error code
3668 * number otherwise and -1 in case of an internal or API error.
3669 */
3670static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003671xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3672 xmlChar **ownerDes,
3673 xmlSchemaTypePtr ownerItem,
3674 xmlAttrPtr attr,
3675 const xmlChar *value,
3676 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003677{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003678
Daniel Veillardc0826a72004-08-10 14:17:33 +00003679 int ret = 0;
3680
3681 /*
3682 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3683 * one is really meant to be used internally, so better not.
3684 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003685 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003686 return (-1);
3687 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3688 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003689 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003690 "Internal error: xmlSchemaPvalueAttrNode, the given "
3691 "type '%s' is not a built-in type.\n",
3692 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003693 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003694 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003695 switch (type->builtInType) {
3696 case XML_SCHEMAS_NCNAME:
3697 ret = xmlValidateNCName(value, 1);
3698 break;
3699 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003700 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003701 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003702 "Internal error: xmlSchemaPvalueAttrNode, use "
3703 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3704 "for extracting QName valueues instead.\n",
3705 NULL, NULL);
3706 return (-1);
3707 case XML_SCHEMAS_ANYURI:
3708 if (value != NULL) {
3709 xmlURIPtr uri = xmlParseURI((const char *) value);
3710 if (uri == NULL)
3711 ret = 1;
3712 else
3713 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003714 }
3715 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003716 case XML_SCHEMAS_TOKEN: {
3717 const xmlChar *cur = value;
3718
3719 if (IS_BLANK_CH(*cur)) {
3720 ret = 1;
3721 } else while (*cur != 0) {
3722 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3723 ret = 1;
3724 break;
3725 } else if (*cur == ' ') {
3726 cur++;
3727 if ((*cur == 0) || (*cur == ' ')) {
3728 ret = 1;
3729 break;
3730 }
3731 } else {
3732 cur++;
3733 }
3734 }
3735 }
3736 break;
3737 case XML_SCHEMAS_LANGUAGE:
3738 if (xmlCheckLanguageID(value) != 1)
3739 ret = 1;
3740 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003741 default: {
3742 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003743 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003744 "Internal error: xmlSchemaPvalueAttrNode, "
3745 "valueidation using the type '%s' is not implemented "
3746 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003747 type->name, NULL);
3748 return (-1);
3749 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003750 }
3751 /*
3752 * TODO: Should we use the S4S error codes instead?
3753 */
3754 if (ret > 0) {
3755 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3756 xmlSchemaPSimpleTypeErr(ctxt,
3757 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3758 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003759 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003760 NULL, NULL, NULL);
3761 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3762 } else {
3763 xmlSchemaPSimpleTypeErr(ctxt,
3764 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3765 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003766 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003767 NULL, NULL, NULL);
3768 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3769 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003770 }
3771 return (ret);
3772}
3773
3774/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003775 * xmlSchemaPValAttrNode:
3776 *
3777 * @ctxt: a schema parser context
3778 * @ownerDes: the designation of the parent element
3779 * @ownerItem: the schema object owner if existent
3780 * @attr: the schema attribute node being validated
3781 * @type: the built-in type to be validated against
3782 * @value: the resulting value if any
3783 *
3784 * Extracts and validates a value against the given built-in type.
3785 * This one is intended to be used internally for validation
3786 * of schema attribute values during parsing of the schema.
3787 *
3788 * Returns 0 if the value is valid, a positive error code
3789 * number otherwise and -1 in case of an internal or API error.
3790 */
3791static int
3792xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3793 xmlChar **ownerDes,
3794 xmlSchemaTypePtr ownerItem,
3795 xmlAttrPtr attr,
3796 xmlSchemaTypePtr type,
3797 const xmlChar **value)
3798{
3799 const xmlChar *val;
3800
3801 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3802 return (-1);
3803
3804 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3805 if (value != NULL)
3806 *value = val;
3807
3808 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3809 val, type));
3810}
3811
3812/**
3813 * xmlSchemaPValAttr:
3814 *
3815 * @ctxt: a schema parser context
3816 * @node: the element node of the attribute
3817 * @ownerDes: the designation of the parent element
3818 * @ownerItem: the schema object owner if existent
3819 * @ownerElem: the owner element node
3820 * @name: the name of the schema attribute node
3821 * @type: the built-in type to be validated against
3822 * @value: the resulting value if any
3823 *
3824 * Extracts and validates a value against the given built-in type.
3825 * This one is intended to be used internally for validation
3826 * of schema attribute values during parsing of the schema.
3827 *
3828 * Returns 0 if the value is valid, a positive error code
3829 * number otherwise and -1 in case of an internal or API error.
3830 */
3831static int
3832xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3833 xmlChar **ownerDes,
3834 xmlSchemaTypePtr ownerItem,
3835 xmlNodePtr ownerElem,
3836 const char *name,
3837 xmlSchemaTypePtr type,
3838 const xmlChar **value)
3839{
3840 xmlAttrPtr attr;
3841
3842 if ((ctxt == NULL) || (type == NULL)) {
3843 if (value != NULL)
3844 *value = NULL;
3845 return (-1);
3846 }
3847 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3848 if (value != NULL)
3849 *value = NULL;
3850 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003851 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003852 "Internal error: xmlSchemaPValAttr, the given "
3853 "type '%s' is not a built-in type.\n",
3854 type->name, NULL);
3855 return (-1);
3856 }
3857 attr = xmlSchemaGetPropNode(ownerElem, name);
3858 if (attr == NULL) {
3859 if (value != NULL)
3860 *value = NULL;
3861 return (0);
3862 }
3863 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
3864 type, value));
3865}
3866/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003867 * xmlSchemaParseAttrDecls:
3868 * @ctxt: a schema validation context
3869 * @schema: the schema being built
3870 * @node: a subtree containing XML Schema informations
3871 * @type: the hosting type
3872 *
3873 * parse a XML schema attrDecls declaration corresponding to
3874 * <!ENTITY % attrDecls
3875 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
3876 */
3877static xmlNodePtr
3878xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3879 xmlNodePtr child, xmlSchemaTypePtr type)
3880{
3881 xmlSchemaAttributePtr lastattr, attr;
3882
3883 lastattr = NULL;
3884 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003885 (IS_SCHEMA(child, "attributeGroup"))) {
3886 attr = NULL;
3887 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003888 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003889 } else if (IS_SCHEMA(child, "attributeGroup")) {
3890 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003891 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003892 }
3893 if (attr != NULL) {
3894 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003895 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3896 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
3897 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 type->attributes = attr;
3899 lastattr = attr;
3900 } else {
3901 lastattr->next = attr;
3902 lastattr = attr;
3903 }
3904 }
3905 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003906 }
3907 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003908 xmlSchemaWildcardPtr wildcard;
3909
3910 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
3911 if (wildcard != NULL) {
3912 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3913 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
3914 else
3915 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003916 }
3917 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003918 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003919 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00003920}
3921
3922/**
3923 * xmlSchemaParseAnnotation:
3924 * @ctxt: a schema validation context
3925 * @schema: the schema being built
3926 * @node: a subtree containing XML Schema informations
3927 *
3928 * parse a XML schema Attrribute declaration
3929 * *WARNING* this interface is highly subject to change
3930 *
William M. Bracke7091952004-05-11 15:09:58 +00003931 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003932 * 1 in case of success.
3933 */
3934static xmlSchemaAnnotPtr
3935xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3936 xmlNodePtr node)
3937{
3938 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003939 xmlNodePtr child = NULL;
3940 xmlAttrPtr attr;
3941 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003942
Daniel Veillardc0826a72004-08-10 14:17:33 +00003943 /*
3944 * INFO: S4S completed.
3945 */
3946 /*
3947 * id = ID
3948 * {any attributes with non-schema namespace . . .}>
3949 * Content: (appinfo | documentation)*
3950 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003951 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3952 return (NULL);
3953 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003954 attr = node->properties;
3955 while (attr != NULL) {
3956 if (((attr->ns == NULL) &&
3957 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
3958 ((attr->ns != NULL) &&
3959 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
3960
3961 xmlSchemaPIllegalAttrErr(ctxt,
3962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3963 NULL, NULL, attr);
3964 }
3965 attr = attr->next;
3966 }
3967 /* TODO: Check id. */
3968
3969 /*
3970 * And now for the children...
3971 */
3972 child = node->children;
3973 while (child != NULL) {
3974 if (IS_SCHEMA(child, "appinfo")) {
3975 /* TODO: make available the content of "appinfo". */
3976 /*
3977 * source = anyURI
3978 * {any attributes with non-schema namespace . . .}>
3979 * Content: ({any})*
3980 */
3981 attr = child->properties;
3982 while (attr != NULL) {
3983 if (((attr->ns == NULL) &&
3984 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
3985 ((attr->ns != NULL) &&
3986 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003987
Daniel Veillardc0826a72004-08-10 14:17:33 +00003988 xmlSchemaPIllegalAttrErr(ctxt,
3989 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3990 NULL, NULL, attr);
3991 }
3992 attr = attr->next;
3993 }
3994 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
3995 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
3996 child = child->next;
3997 } else if (IS_SCHEMA(child, "documentation")) {
3998 /* TODO: make available the content of "documentation". */
3999 /*
4000 * source = anyURI
4001 * {any attributes with non-schema namespace . . .}>
4002 * Content: ({any})*
4003 */
4004 attr = child->properties;
4005 while (attr != NULL) {
4006 if (attr->ns == NULL) {
4007 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4008 xmlSchemaPIllegalAttrErr(ctxt,
4009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4010 NULL, NULL, attr);
4011 }
4012 } else {
4013 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4014 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4015 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4016
4017 xmlSchemaPIllegalAttrErr(ctxt,
4018 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4019 NULL, NULL, attr);
4020 }
4021 }
4022 attr = attr->next;
4023 }
4024 /*
4025 * Attribute "xml:lang".
4026 */
4027 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4028 if (attr != NULL)
4029 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4030 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4031 child = child->next;
4032 } else {
4033 if (!barked)
4034 xmlSchemaPContentErr(ctxt,
4035 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4036 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4037 barked = 1;
4038 child = child->next;
4039 }
4040 }
4041
Daniel Veillard4255d502002-04-16 15:50:10 +00004042 return (ret);
4043}
4044
4045/**
4046 * xmlSchemaParseFacet:
4047 * @ctxt: a schema validation context
4048 * @schema: the schema being built
4049 * @node: a subtree containing XML Schema informations
4050 *
4051 * parse a XML schema Facet declaration
4052 * *WARNING* this interface is highly subject to change
4053 *
4054 * Returns the new type structure or NULL in case of error
4055 */
4056static xmlSchemaFacetPtr
4057xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004058 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004059{
4060 xmlSchemaFacetPtr facet;
4061 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004062 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004063
4064 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4065 return (NULL);
4066
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004067 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004068 if (facet == NULL) {
4069 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4070 return (NULL);
4071 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004073 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004074 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004075 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4076 "Facet %s has no value\n", node->name, NULL);
4077 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004078 return (NULL);
4079 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004080 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004081 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004082 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004083 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004086 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004087 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004088 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004089 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004090 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004091 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004093 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004094 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004095 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004096 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004097 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004098 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004099 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004100 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4102 } else if (IS_SCHEMA(node, "minLength")) {
4103 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4104 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004105 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4106 "Unknown facet type %s\n", node->name, NULL);
4107 xmlSchemaFreeFacet(facet);
4108 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004109 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004110 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004111 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004112 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4113 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4114 const xmlChar *fixed;
4115
4116 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4117 if (fixed != NULL) {
4118 if (xmlStrEqual(fixed, BAD_CAST "true"))
4119 facet->fixed = 1;
4120 }
4121 }
4122
Daniel Veillard4255d502002-04-16 15:50:10 +00004123 child = node->children;
4124
4125 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004126 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004128 }
4129 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004130 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4131 "Facet %s has unexpected child content\n",
4132 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004133 }
4134 return (facet);
4135}
4136
4137/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004138 * xmlSchemaParseWildcardNs:
4139 * @ctxt: a schema parser context
4140 * @wildc: the wildcard, already created
4141 * @node: a subtree containing XML Schema informations
4142 *
4143 * Parses the attribute "processContents" and "namespace"
4144 * of a xsd:anyAttribute and xsd:any.
4145 * *WARNING* this interface is highly subject to change
4146 *
4147 * Returns 0 if everything goes fine, a positive error code
4148 * if something is not valid and -1 if an internal error occurs.
4149 */
4150static int
4151xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4152 xmlSchemaPtr schema,
4153 xmlSchemaWildcardPtr wildc,
4154 xmlNodePtr node)
4155{
4156 const xmlChar *pc, *ns, *dictnsItem;
4157 int ret = 0;
4158 xmlChar *nsItem;
4159 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4160 xmlAttrPtr attr;
4161
4162 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4163 if ((pc == NULL)
4164 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4165 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4166 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4167 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4168 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4169 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4170 } else {
4171 xmlSchemaPSimpleTypeErr(ctxt,
4172 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4173 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004174 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004175 NULL, NULL, NULL);
4176 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4177 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4178 }
4179 /*
4180 * Build the namespace constraints.
4181 */
4182 attr = xmlSchemaGetPropNode(node, "namespace");
4183 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4184 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4185 wildc->any = 1;
4186 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4187 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4188 if (wildc->negNsSet == NULL) {
4189 return (-1);
4190 }
4191 wildc->negNsSet->value = schema->targetNamespace;
4192 } else {
4193 const xmlChar *end, *cur;
4194
4195 cur = ns;
4196 do {
4197 while (IS_BLANK_CH(*cur))
4198 cur++;
4199 end = cur;
4200 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4201 end++;
4202 if (end == cur)
4203 break;
4204 nsItem = xmlStrndup(cur, end - cur);
4205 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4206 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4207 xmlSchemaPSimpleTypeErr(ctxt,
4208 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4209 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004210 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004211 "((##any | ##other) | List of (anyURI | "
4212 "(##targetNamespace | ##local)))",
4213 nsItem, NULL, NULL, NULL);
4214 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4215 } else {
4216 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4217 dictnsItem = schema->targetNamespace;
4218 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4219 dictnsItem = NULL;
4220 } else {
4221 /*
4222 * Validate the item (anyURI).
4223 */
4224 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4225 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4226 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4227 }
4228 /*
4229 * Avoid dublicate namespaces.
4230 */
4231 tmp = wildc->nsSet;
4232 while (tmp != NULL) {
4233 if (dictnsItem == tmp->value)
4234 break;
4235 tmp = tmp->next;
4236 }
4237 if (tmp == NULL) {
4238 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4239 if (tmp == NULL) {
4240 xmlFree(nsItem);
4241 return (-1);
4242 }
4243 tmp->value = dictnsItem;
4244 tmp->next = NULL;
4245 if (wildc->nsSet == NULL)
4246 wildc->nsSet = tmp;
4247 else
4248 lastNs->next = tmp;
4249 lastNs = tmp;
4250 }
4251
4252 }
4253 xmlFree(nsItem);
4254 cur = end;
4255 } while (*cur != 0);
4256 }
4257 return (ret);
4258}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004259
4260static int
4261xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4262 xmlSchemaTypePtr item,
4263 xmlNodePtr node,
4264 int minOccurs,
4265 int maxOccurs) {
4266
4267 if (maxOccurs != UNBOUNDED) {
4268 /*
4269 * TODO: Maby we should better not create the particle,
4270 * if min/max is invalid, since it could confuse the build of the
4271 * content model.
4272 */
4273 /*
4274 * 3.9.6 Schema Component Constraint: Particle Correct
4275 *
4276 */
4277 if (maxOccurs < 1) {
4278 /*
4279 * 2.2 {max occurs} must be greater than or equal to 1.
4280 */
4281 xmlSchemaPCustomAttrErr(ctxt,
4282 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4283 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4284 "The value must be greater than or equal to 1");
4285 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4286 } else if (minOccurs > maxOccurs) {
4287 /*
4288 * 2.1 {min occurs} must not be greater than {max occurs}.
4289 */
4290 xmlSchemaPCustomAttrErr(ctxt,
4291 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4292 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4293 "The value must not be greater than the value of 'maxOccurs'");
4294 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4295 }
4296 }
4297 return (0);
4298}
4299
Daniel Veillardc0826a72004-08-10 14:17:33 +00004300/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004301 * xmlSchemaParseAny:
4302 * @ctxt: a schema validation context
4303 * @schema: the schema being built
4304 * @node: a subtree containing XML Schema informations
4305 *
4306 * parse a XML schema Any declaration
4307 * *WARNING* this interface is highly subject to change
4308 *
4309 * Returns the new type structure or NULL in case of error
4310 */
4311static xmlSchemaTypePtr
4312xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4313 xmlNodePtr node)
4314{
4315 xmlSchemaTypePtr type;
4316 xmlNodePtr child = NULL;
4317 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004318 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004319 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004320
4321 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4322 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004323 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4324 "(nonNegativeInteger | unbounded)");
4325 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4326 "nonNegativeInteger");
4327 if ((minOccurs == 0) && (maxOccurs == 0))
4328 return (NULL);
4329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004331 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004332 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004333 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004334 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004335 type->type = XML_SCHEMA_TYPE_ANY;
4336
Daniel Veillardc0826a72004-08-10 14:17:33 +00004337 wildc = xmlSchemaAddWildcard(ctxt);
4338 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004339 * Check min/max sanity.
4340 */
4341 type->maxOccurs = maxOccurs;
4342 type->minOccurs = minOccurs;
4343 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4344 node, type->minOccurs, type->maxOccurs);
4345 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004346 * This is not nice, since it is won't be used as a attribute wildcard,
4347 * but better than adding a field to the structure.
4348 */
4349 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004350 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004351 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004352 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004353 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4354 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004355 }
4356 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004357 xmlSchemaPErr2(ctxt, node, child,
4358 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4359 "Sequence %s has unexpected content\n", type->name,
4360 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004361 }
4362
4363 return (type);
4364}
4365
4366/**
4367 * xmlSchemaParseNotation:
4368 * @ctxt: a schema validation context
4369 * @schema: the schema being built
4370 * @node: a subtree containing XML Schema informations
4371 *
4372 * parse a XML schema Notation declaration
4373 *
4374 * Returns the new structure or NULL in case of error
4375 */
4376static xmlSchemaNotationPtr
4377xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004379{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004380 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 xmlSchemaNotationPtr ret;
4382 xmlNodePtr child = NULL;
4383
4384 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4385 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004386 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004388 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4389 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 return (NULL);
4391 }
4392 ret = xmlSchemaAddNotation(ctxt, schema, name);
4393 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 return (NULL);
4395 }
4396 child = node->children;
4397 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004398 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4399 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004400 }
4401 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 xmlSchemaPErr2(ctxt, node, child,
4403 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4404 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
4406
4407 return (ret);
4408}
4409
4410/**
4411 * xmlSchemaParseAnyAttribute:
4412 * @ctxt: a schema validation context
4413 * @schema: the schema being built
4414 * @node: a subtree containing XML Schema informations
4415 *
4416 * parse a XML schema AnyAttrribute declaration
4417 * *WARNING* this interface is highly subject to change
4418 *
4419 * Returns an attribute def structure or NULL
4420 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004421static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4423 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004424{
Daniel Veillard3646d642004-06-02 19:19:14 +00004425 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004427
4428 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4429 return (NULL);
4430
Daniel Veillard3646d642004-06-02 19:19:14 +00004431 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 if (ret == NULL) {
4433 return (NULL);
4434 }
William M. Bracke7091952004-05-11 15:09:58 +00004435 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004436 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004437 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4438 xmlSchemaFreeWildcard(ret);
4439 return (NULL);
4440 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 child = node->children;
4442 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004443 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4444 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 }
4446 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004447 /* TODO: Change the error code. */
4448 xmlSchemaPContentErr(ctxt,
4449 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
4450 NULL, NULL, node, child,
4451 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 }
4453
4454 return (ret);
4455}
4456
4457
4458/**
4459 * xmlSchemaParseAttribute:
4460 * @ctxt: a schema validation context
4461 * @schema: the schema being built
4462 * @node: a subtree containing XML Schema informations
4463 *
4464 * parse a XML schema Attrribute declaration
4465 * *WARNING* this interface is highly subject to change
4466 *
William M. Bracke7091952004-05-11 15:09:58 +00004467 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 */
4469static xmlSchemaAttributePtr
4470xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004471 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004472{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004473 const xmlChar *name, *attrValue;
4474 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004475 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004476 xmlNodePtr child = NULL;
4477 xmlAttrPtr attr, nameAttr;
4478 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004479
4480 /*
4481 * Note that the w3c spec assumes the schema to be validated with schema
4482 * for schemas beforehand.
4483 *
4484 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004485 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004486
4487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4488 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004489 attr = xmlSchemaGetPropNode(node, "ref");
4490 nameAttr = xmlSchemaGetPropNode(node, "name");
4491
4492 if ((attr == NULL) && (nameAttr == NULL)) {
4493 /*
4494 * 3.2.3 : 3.1
4495 * One of ref or name must be present, but not both
4496 */
4497 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4498 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4499 "One of the attributes 'ref' or 'name' must be present");
4500 return (NULL);
4501 }
4502 if ((topLevel) || (attr == NULL)) {
4503 if (nameAttr == NULL) {
4504 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4505 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4506 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004507 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004508 }
4509 } else
4510 isRef = 1;
4511
4512 if (isRef) {
4513 char buf[100];
4514 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4515
4516 /*
4517 * Parse as attribute reference.
4518 */
4519 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4520 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4521 &refPrefix, &ref) != 0) {
4522 return (NULL);
4523 }
4524 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4525 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004526 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004527 if (ret == NULL) {
4528 if (repName != NULL)
4529 xmlFree(repName);
4530 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004532 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4533 ret->node = node;
4534 ret->refNs = refNs;
4535 ret->refPrefix = refPrefix;
4536 ret->ref = ref;
4537 /*
4538 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4539 */
4540 if (nameAttr != NULL)
4541 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4542 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4543 "ref", "name");
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 "type") ||
4551 xmlStrEqual(attr->name, BAD_CAST "form")) {
4552 /*
4553 * 3.2.3 : 3.2
4554 * If ref is present, then all of <simpleType>,
4555 * form and type must be absent.
4556 */
4557 xmlSchemaPIllegalAttrErr(ctxt,
4558 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4559 (xmlSchemaTypePtr) ret, attr);
4560 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4561 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4562 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4563 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4564 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4565 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4566 xmlSchemaPIllegalAttrErr(ctxt,
4567 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4568 &repName, (xmlSchemaTypePtr) ret, attr);
4569 }
4570 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4571 xmlSchemaPIllegalAttrErr(ctxt,
4572 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4573 &repName, (xmlSchemaTypePtr) ret, attr);
4574 }
4575 attr = attr->next;
4576 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004577 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004578 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004579
4580 /*
4581 * Parse as attribute declaration.
4582 */
4583 if (xmlSchemaPValAttrNode(ctxt,
4584 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4585 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4586 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004587 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004588 /*
4589 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4590 */
4591 /*
4592 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4593 */
4594 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4595 xmlSchemaPSimpleTypeErr(ctxt,
4596 XML_SCHEMAP_NO_XMLNS,
4597 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004598 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004599 "The value must not match 'xmlns'",
4600 NULL, NULL);
4601 if (repName != NULL)
4602 xmlFree(repName);
4603 return (NULL);
4604 }
4605 /*
4606 * Evaluate the target namespace
4607 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004608 if (topLevel) {
4609 ns = schema->targetNamespace;
4610 } else {
4611 attr = xmlSchemaGetPropNode(node, "form");
4612 if (attr != NULL) {
4613 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4614 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4615 ns = schema->targetNamespace;
4616 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4617 xmlSchemaPSimpleTypeErr(ctxt,
4618 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4619 &repName, NULL, (xmlNodePtr) attr,
4620 NULL, "(qualified | unqualified)",
4621 attrValue, NULL, NULL, NULL);
4622 }
4623 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4624 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004625 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004626 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004627 if (ret == NULL) {
4628 if (repName != NULL)
4629 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004630 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004631 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004632 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4633 ret->node = node;
4634 if (topLevel)
4635 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4636 /*
4637 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4638 */
4639 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4640 xmlSchemaPCustomErr(ctxt,
4641 XML_SCHEMAP_NO_XSI,
4642 &repName, (xmlSchemaTypePtr) ret, node,
4643 "The target namespace must not match '%s'",
4644 xmlSchemaInstanceNs);
4645 }
4646 /*
4647 * Check for illegal attributes.
4648 */
4649 attr = node->properties;
4650 while (attr != NULL) {
4651 if (attr->ns == NULL) {
4652 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4653 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4654 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4655 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4656 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4657 if ((topLevel) ||
4658 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4659 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4660 xmlSchemaPIllegalAttrErr(ctxt,
4661 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4662 &repName, (xmlSchemaTypePtr) ret, attr);
4663 }
4664 }
4665 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4666 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4667 &repName, (xmlSchemaTypePtr) ret, attr);
4668 }
4669 attr = attr->next;
4670 }
4671 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4672 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004673 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004674 /* TODO: Check ID. */
4675 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004676 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004677 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004678 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004679 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4680 if (ret->defValue != NULL)
4681 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4682 /*
4683 * Attribute "default".
4684 */
4685 attr = xmlSchemaGetPropNode(node, "default");
4686 if (attr != NULL) {
4687 /*
4688 * 3.2.3 : 1
4689 * default and fixed must not both be present.
4690 */
4691 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4692 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4693 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4694 } else
4695 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4696 }
4697 if (topLevel == 0) {
4698 /*
4699 * Attribute "use".
4700 */
4701 attr = xmlSchemaGetPropNode(node, "use");
4702 if (attr != NULL) {
4703 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4704 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4705 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4706 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4707 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4708 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4709 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4710 else
4711 xmlSchemaPSimpleTypeErr(ctxt,
4712 XML_SCHEMAP_INVALID_ATTR_USE,
4713 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004714 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004715 attrValue, NULL, NULL, NULL);
4716 } else
4717 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4718 /*
4719 * 3.2.3 : 2
4720 * If default and use are both present, use must have
4721 * the actual value optional.
4722 */
4723 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4724 (ret->defValue != NULL) &&
4725 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4726 xmlSchemaPSimpleTypeErr(ctxt,
4727 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4728 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004729 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004730 "The value must be 'optional' if the attribute "
4731 "'default' is present as well", NULL, NULL);
4732 }
4733 }
4734 /*
4735 * And now for the children...
4736 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004737 child = node->children;
4738 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004739 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4740 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004741 }
4742 if (isRef) {
4743 if (child != NULL) {
4744 if (IS_SCHEMA(child, "simpleType"))
4745 /*
4746 * 3.2.3 : 3.2
4747 * If ref is present, then all of <simpleType>,
4748 * form and type must be absent.
4749 */
4750 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4751 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4752 "(annotation?)");
4753 else
4754 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4755 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4756 "(annotation?)");
4757 }
4758 } else {
4759 if (IS_SCHEMA(child, "simpleType")) {
4760 if (ret->typeName != NULL) {
4761 /*
4762 * 3.2.3 : 4
4763 * type and <simpleType> must not both be present.
4764 */
4765 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4766 &repName, (xmlSchemaTypePtr) ret, node, child,
4767 "The attribute 'type' and the <simpleType> child "
4768 "are mutually exclusive", NULL);
4769 } else
4770 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4771 child = child->next;
4772 }
4773 if (child != NULL)
4774 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4775 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4776 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004777 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004778 /*
4779 * Cleanup.
4780 */
4781 if (repName != NULL)
4782 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004783 return (ret);
4784}
4785
4786/**
4787 * xmlSchemaParseAttributeGroup:
4788 * @ctxt: a schema validation context
4789 * @schema: the schema being built
4790 * @node: a subtree containing XML Schema informations
4791 *
4792 * parse a XML schema Attribute Group declaration
4793 * *WARNING* this interface is highly subject to change
4794 *
4795 * Returns the attribute group or NULL in case of error.
4796 */
4797static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004798xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004799 xmlSchemaPtr schema, xmlNodePtr node,
4800 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004801{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004802 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004803 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004805 const xmlChar *oldcontainer;
4806 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004807
4808 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4809 return (NULL);
4810 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004811 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004812 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
4814 if (ref == NULL) {
4815 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004816 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
4817 "Attribute group or particle: One of the attributes 'name' "
4818 "or 'ref' must be present.\n", NULL,
4819 NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 return (NULL);
4821 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004822 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
4823 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 if (name == NULL) {
4825 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
4826 return (NULL);
4827 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004828 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004829 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004831 return (NULL);
4832 }
4833 ret->ref = ref;
4834 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004835 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00004836 if (topLevel)
4837 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004838 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00004839 child = node->children;
4840 ctxt->container = name;
4841 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004842 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4843 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004844 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004845 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004846 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004847 xmlSchemaPErr2(ctxt, node, child,
4848 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004849 "Attribute group '%s' has unexpected content.\n", name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004850 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004851 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004852 ctxt->container = oldcontainer;
4853 return (ret);
4854}
4855
4856/**
William M. Brack2f2a6632004-08-20 23:09:47 +00004857 * xmlSchemaPValAttrFormDefault:
4858 * @value: the value
4859 * @flags: the flags to be modified
4860 * @flagQualified: the specific flag for "qualified"
4861 *
4862 * Returns 0 if the value is valid, 1 otherwise.
4863 */
4864static int
4865xmlSchemaPValAttrFormDefault(const xmlChar *value,
4866 int *flags,
4867 int flagQualified)
4868{
4869 if (xmlStrEqual(value, BAD_CAST "qualified")) {
4870 if ((*flags & flagQualified) == 0)
4871 *flags |= flagQualified;
4872 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
4873 return (1);
4874
4875 return (0);
4876}
4877
4878/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004879 * xmlSchemaPValAttrBlockFinal:
4880 * @value: the value
4881 * @flags: the flags to be modified
4882 * @flagAll: the specific flag for "#all"
4883 * @flagExtension: the specific flag for "extension"
4884 * @flagRestriction: the specific flag for "restriction"
4885 * @flagSubstitution: the specific flag for "substitution"
4886 * @flagList: the specific flag for "list"
4887 * @flagUnion: the specific flag for "union"
4888 *
4889 * Validates the value of the attribute "final" and "block". The value
4890 * is converted into the specified flag values and returned in @flags.
4891 *
4892 * Returns 0 if the value is valid, 1 otherwise.
4893 */
4894
4895static int
4896xmlSchemaPValAttrBlockFinal(const xmlChar *value,
4897 int *flags,
4898 int flagAll,
4899 int flagExtension,
4900 int flagRestriction,
4901 int flagSubstitution,
4902 int flagList,
4903 int flagUnion)
4904{
4905 int ret = 0;
4906
4907 /*
4908 * TODO: This does not check for dublicate entries.
4909 */
William M. Brack2f2a6632004-08-20 23:09:47 +00004910 if (value == NULL)
4911 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004912 if (xmlStrEqual(value, BAD_CAST "#all")) {
4913 if (flagAll != -1)
4914 *flags |= flagAll;
4915 else {
4916 if (flagExtension != -1)
4917 *flags |= flagExtension;
4918 if (flagRestriction != -1)
4919 *flags |= flagRestriction;
4920 if (flagSubstitution != -1)
4921 *flags |= flagSubstitution;
4922 if (flagList != -1)
4923 *flags |= flagList;
4924 if (flagUnion != -1)
4925 *flags |= flagUnion;
4926 }
4927 } else {
4928 const xmlChar *end, *cur = value;
4929 xmlChar *item;
4930
4931 do {
4932 while (IS_BLANK_CH(*cur))
4933 cur++;
4934 end = cur;
4935 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4936 end++;
4937 if (end == cur)
4938 break;
4939 item = xmlStrndup(cur, end - cur);
4940 if (xmlStrEqual(item, BAD_CAST "extension")) {
4941 if (flagExtension != -1) {
4942 if ((*flags & flagExtension) == 0)
4943 *flags |= flagExtension;
4944 } else
4945 ret = 1;
4946 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4947 if (flagRestriction != -1) {
4948 if ((*flags & flagRestriction) == 0)
4949 *flags |= flagRestriction;
4950 } else
4951 ret = 1;
4952 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
4953 if (flagSubstitution != -1) {
4954 if ((*flags & flagSubstitution) == 0)
4955 *flags |= flagSubstitution;
4956 } else
4957 ret = 1;
4958 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4959 if (flagList != -1) {
4960 if ((*flags & flagList) == 0)
4961 *flags |= flagList;
4962 } else
4963 ret = 1;
4964 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4965 if (flagUnion != -1) {
4966 if ((*flags & flagUnion) == 0)
4967 *flags |= flagUnion;
4968 } else
4969 ret = 1;
4970 } else
4971 ret = 1;
4972 if (item != NULL)
4973 xmlFree(item);
4974 cur = end;
4975 } while ((ret == 0) && (*cur != 0));
4976 }
4977
4978 return (ret);
4979}
4980
4981/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004982 * xmlSchemaParseElement:
4983 * @ctxt: a schema validation context
4984 * @schema: the schema being built
4985 * @node: a subtree containing XML Schema informations
4986 *
4987 * parse a XML schema Element declaration
4988 * *WARNING* this interface is highly subject to change
4989 *
William M. Bracke7091952004-05-11 15:09:58 +00004990 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004991 */
4992static xmlSchemaElementPtr
4993xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004994 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004995{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004996 const xmlChar *name = NULL;
4997 const xmlChar *attrValue;
4998 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004999 xmlSchemaElementPtr ret;
5000 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005001 const xmlChar *oldcontainer;
5002 xmlAttrPtr attr, nameAttr;
5003 int minOccurs, maxOccurs;
5004 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005005
5006 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5007 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005008
Daniel Veillard4255d502002-04-16 15:50:10 +00005009 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5010 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005011
Daniel Veillardc0826a72004-08-10 14:17:33 +00005012 oldcontainer = ctxt->container;
5013
5014 nameAttr = xmlSchemaGetPropNode(node, "name");
5015 attr = xmlSchemaGetPropNode(node, "ref");
5016 if ((topLevel) || (attr == NULL)) {
5017 if (nameAttr == NULL) {
5018 xmlSchemaPMissingAttrErr(ctxt,
5019 XML_SCHEMAP_S4S_ATTR_MISSING,
5020 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5021 "name", NULL);
5022 return (NULL);
5023 }
5024 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5025 } else {
5026 isRef = 1;
5027
5028 }
5029 /*
5030 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5031 * to no component at all
5032 * TODO: It might be better to validate the element, even if it won't be
5033 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005034 */
5035 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5036 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005037 if ((minOccurs == 0) && (maxOccurs == 0))
5038 return (NULL);
5039 /*
5040 * If we get a "ref" attribute on a local <element> we will assume it's
5041 * a reference - even if there's a "name" attribute; this seems to be more
5042 * robust.
5043 */
5044 if (isRef) {
5045 char buf[100];
5046 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5047
5048 /*
5049 * Parse as a particle.
5050 */
5051 xmlSchemaPValAttrNodeQName(ctxt, schema,
5052 (xmlChar **) &xmlSchemaElemDesAttrRef,
5053 NULL, attr, &refNs, &refPrefix, &ref);
5054
5055 snprintf(buf, 99, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005056 name = (const xmlChar *) buf;
5057 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005058 if (ret == NULL) {
5059 if (repName != NULL)
5060 xmlFree(repName);
5061 return (NULL);
5062 }
5063 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5064 ret->node = node;
5065 ret->ref = ref;
5066 ret->refNs = refNs;
5067 ret->refPrefix = refPrefix;
5068 ret->flags |= XML_SCHEMAS_ELEM_REF;
5069 /*
5070 * Check for illegal attributes.
5071 */
5072 /*
5073 * 3.3.3 : 2.1
5074 * One of ref or name must be present, but not both
5075 */
5076 if (nameAttr != NULL) {
5077 xmlSchemaPMutualExclAttrErr(ctxt,
5078 XML_SCHEMAP_SRC_ELEMENT_2_1,
5079 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5080 "ref", "name");
5081 }
5082 /* 3.3.3 : 2.2 */
5083 attr = node->properties;
5084 while (attr != NULL) {
5085 if (attr->ns == NULL) {
5086 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5087 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5088 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5089 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5090 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
5091 xmlSchemaPCustomAttrErr(ctxt,
5092 XML_SCHEMAP_SRC_ELEMENT_2_2,
5093 &repName, (xmlSchemaTypePtr) ret, attr,
5094 "Only the attributes 'minOccurs', 'maxOccurs' and "
5095 "'id' are allowed in addition to 'ref'");
5096 break;
5097 }
5098 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5099 xmlSchemaPIllegalAttrErr(ctxt,
5100 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5101 &repName, (xmlSchemaTypePtr) ret, attr);
5102 }
5103 attr = attr->next;
5104 }
5105 } else {
5106 const xmlChar *ns = NULL, *fixed;
5107
5108 /*
5109 * Parse as an element declaration.
5110 */
5111 if (xmlSchemaPValAttrNode(ctxt,
5112 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5113 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5114 return (NULL);
5115 /*
5116 * Evaluate the target namespace.
5117 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005118 if (topLevel) {
5119 ns = schema->targetNamespace;
5120 } else {
5121 attr = xmlSchemaGetPropNode(node, "form");
5122 if (attr != NULL) {
5123 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5124 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005125 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005126 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5127 xmlSchemaPSimpleTypeErr(ctxt,
5128 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5129 &repName, NULL, (xmlNodePtr) attr,
5130 NULL, "(qualified | unqualified)",
5131 attrValue, NULL, NULL, NULL);
5132 }
5133 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5134 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005135 }
5136 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005137 if (ret == NULL) {
5138 if (repName != NULL)
5139 xmlFree(repName);
5140 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005141 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005142 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5143 ret->node = node;
5144 /*
5145 * Check for illegal attributes.
5146 */
William M. Bracke7091952004-05-11 15:09:58 +00005147 attr = node->properties;
5148 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005149 if (attr->ns == NULL) {
5150 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5151 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5152 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5153 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5154 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5155 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
5156 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
5157 if (topLevel == 0) {
5158 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5159 /*
5160 * 3.3.6 : 3 If there is a non-·absent· {substitution
5161 * group affiliation}, then {scope} must be global.
5162 * TODO: This one is redundant, since the S4S does
5163 * prohibit this attribute on local declarations already;
5164 * so why an explicit error code? Weird spec.
William M. Brack2f2a6632004-08-20 23:09:47 +00005165 * TODO: Move this to the proper constraint layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005166 */
5167 xmlSchemaPIllegalAttrErr(ctxt,
5168 XML_SCHEMAP_E_PROPS_CORRECT_3,
5169 &repName, (xmlSchemaTypePtr) ret, attr);
5170 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5171 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5172 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005173
Daniel Veillardc0826a72004-08-10 14:17:33 +00005174 xmlSchemaPIllegalAttrErr(ctxt,
5175 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5176 &repName, (xmlSchemaTypePtr) ret, attr);
5177 }
5178 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5179 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5180 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5181
5182 xmlSchemaPIllegalAttrErr(ctxt,
5183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5184 &repName, (xmlSchemaTypePtr) ret, attr);
5185 }
5186 }
5187 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5188
5189 xmlSchemaPIllegalAttrErr(ctxt,
5190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5191 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005192 }
5193 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005194 }
William M. Bracke7091952004-05-11 15:09:58 +00005195 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005196 * Extract/validate attributes.
5197 */
5198 if (topLevel) {
5199 /*
5200 * Process top attributes of global element declarations here.
5201 */
5202 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5203 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5204 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5205 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5206 &(ret->substGroupNs), NULL, &(ret->substGroup));
5207 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5208 node, "abstract", 0))
5209 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5210 /*
5211 * Attribute "final".
5212 */
5213 attr = xmlSchemaGetPropNode(node, "final");
5214 if (attr == NULL) {
5215 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5216 } else {
5217 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5218 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5219 -1,
5220 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5221 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5222 xmlSchemaPSimpleTypeErr(ctxt,
5223 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5224 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005225 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005226 attrValue, NULL, NULL, NULL);
5227 }
5228 }
5229 }
5230 /*
5231 * Attribute "block".
5232 */
5233 attr = xmlSchemaGetPropNode(node, "block");
5234 if (attr == NULL) {
5235 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5236 } else {
5237 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5238 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5239 -1,
5240 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5241 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5242 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5243 xmlSchemaPSimpleTypeErr(ctxt,
5244 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5245 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005246 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005247 "restriction | substitution))", attrValue,
5248 NULL, NULL, NULL);
5249 }
5250 }
5251 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5252 node, "nillable", 0))
5253 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005254
Daniel Veillardc0826a72004-08-10 14:17:33 +00005255 xmlSchemaPValAttrQName(ctxt, schema,
5256 &repName, (xmlSchemaTypePtr) ret, node,
5257 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005258
Daniel Veillardc0826a72004-08-10 14:17:33 +00005259 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5260 attr = xmlSchemaGetPropNode(node, "fixed");
5261 if (attr != NULL) {
5262 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5263 if (ret->value != NULL) {
5264 /*
5265 * 3.3.3 : 1
5266 * default and fixed must not both be present.
5267 */
5268 xmlSchemaPMutualExclAttrErr(ctxt,
5269 XML_SCHEMAP_SRC_ELEMENT_1,
5270 &repName, (xmlSchemaTypePtr) ret, attr,
5271 "default", "fixed");
5272 } else {
5273 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5274 ret->value = fixed;
5275 }
5276 }
5277 }
5278 /*
5279 * Extract/validate common attributes.
5280 */
5281 /* TODO: Check ID: */
5282 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5283 ret->minOccurs = minOccurs;
5284 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005285 if (topLevel != 1)
5286 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5287 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005288 /*
5289 * And now for the children...
5290 */
5291 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005292 child = node->children;
5293 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005294 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5295 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005296 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005297 if (isRef) {
5298 if (child != NULL) {
5299 xmlSchemaPContentErr(ctxt,
5300 XML_SCHEMAP_SRC_ELEMENT_2_2,
5301 &repName, (xmlSchemaTypePtr) ret, node, child,
5302 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005303 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005304 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005305 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005306 /*
5307 * 3.3.3 : 3
5308 * "type" and either <simpleType> or <complexType> are mutually
5309 * exclusive
5310 */
William M. Bracke7091952004-05-11 15:09:58 +00005311 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005312 xmlSchemaPContentErr(ctxt,
5313 XML_SCHEMAP_SRC_ELEMENT_3,
5314 &repName, (xmlSchemaTypePtr) ret, node, child,
5315 "The attribute 'type' and the <complexType> child are "
5316 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005317 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005318 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005319 child = child->next;
5320 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005321 /*
5322 * 3.3.3 : 3
5323 * "type" and either <simpleType> or <complexType> are
5324 * mutually exclusive
5325 */
William M. Bracke7091952004-05-11 15:09:58 +00005326 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005327 xmlSchemaPContentErr(ctxt,
5328 XML_SCHEMAP_SRC_ELEMENT_3,
5329 &repName, (xmlSchemaTypePtr) ret, node, child,
5330 "The attribute 'type' and the <simpleType> child are "
5331 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005332 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005333 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005334 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005335 }
William M. Bracke7091952004-05-11 15:09:58 +00005336 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005338 TODO child = child->next;
5339 }
5340 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 xmlSchemaPContentErr(ctxt,
5342 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5343 &repName, (xmlSchemaTypePtr) ret, node, child,
5344 NULL, "(annotation?, ((simpleType | complexType)?, "
5345 "(unique | key | keyref)*))");
5346 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005347
Daniel Veillardc0826a72004-08-10 14:17:33 +00005348 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005350 /*
5351 * Cleanup.
5352 */
5353 if (repName != NULL)
5354 xmlFree(repName);
5355 /*
5356 * NOTE: Element Declaration Representation OK 4. will be checked at a
5357 * different layer.
5358 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 return (ret);
5360}
5361
5362/**
5363 * xmlSchemaParseUnion:
5364 * @ctxt: a schema validation context
5365 * @schema: the schema being built
5366 * @node: a subtree containing XML Schema informations
5367 *
5368 * parse a XML schema Union definition
5369 * *WARNING* this interface is highly subject to change
5370 *
William M. Bracke7091952004-05-11 15:09:58 +00005371 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005372 * 1 in case of success.
5373 */
5374static xmlSchemaTypePtr
5375xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005377{
5378 xmlSchemaTypePtr type, subtype, last = NULL;
5379 xmlNodePtr child = NULL;
5380 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005381 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005382
5383 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5384 return (NULL);
5385
William M. Brack2f2a6632004-08-20 23:09:47 +00005386 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5387 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 if (type == NULL)
5389 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005390 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005392 /*
5393 * Check for illegal attributes.
5394 */
5395 attr = node->properties;
5396 while (attr != NULL) {
5397 if (attr->ns == NULL) {
5398 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5399 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5400 xmlSchemaPIllegalAttrErr(ctxt,
5401 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5402 NULL, type, attr);
5403 }
5404 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5405 xmlSchemaPIllegalAttrErr(ctxt,
5406 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5407 NULL, type, attr);
5408 }
5409 attr = attr->next;
5410 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005411 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005412 /*
5413 * Attribute "memberTypes". This is a list of QNames.
5414 * TODO: Validate the QNames.
5415 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005416 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005417 /*
5418 * And now for the children...
5419 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005420 child = node->children;
5421 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005422 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5423 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005424 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005425 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005426 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005427 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005428 if (subtype != NULL) {
5429 if (last == NULL) {
5430 type->subtypes = subtype;
5431 last = subtype;
5432 } else {
5433 last->next = subtype;
5434 last = subtype;
5435 }
5436 last->next = NULL;
5437 }
5438 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005439 }
5440 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005441 /* TODO: Think about the error code. */
5442 xmlSchemaPContentErr(ctxt,
5443 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5444 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005445 }
5446 return (type);
5447}
5448
5449/**
5450 * xmlSchemaParseList:
5451 * @ctxt: a schema validation context
5452 * @schema: the schema being built
5453 * @node: a subtree containing XML Schema informations
5454 *
5455 * parse a XML schema List definition
5456 * *WARNING* this interface is highly subject to change
5457 *
William M. Bracke7091952004-05-11 15:09:58 +00005458 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005459 * 1 in case of success.
5460 */
5461static xmlSchemaTypePtr
5462xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005464{
5465 xmlSchemaTypePtr type, subtype;
5466 xmlNodePtr child = NULL;
5467 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005468 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005469
5470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5471 return (NULL);
5472
William M. Brack2f2a6632004-08-20 23:09:47 +00005473 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5474 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005475 if (type == NULL)
5476 return (NULL);
5477 type->node = node;
5478 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005479 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005480 /*
5481 * Check for illegal attributes.
5482 */
5483 attr = node->properties;
5484 while (attr != NULL) {
5485 if (attr->ns == NULL) {
5486 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5487 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5488 xmlSchemaPIllegalAttrErr(ctxt,
5489 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5490 NULL, type, attr);
5491 }
5492 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5493 xmlSchemaPIllegalAttrErr(ctxt,
5494 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5495 NULL, type, attr);
5496 }
5497 attr = attr->next;
5498 }
5499 /*
5500 * Attribute "itemType".
5501 */
5502 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5503 node, "itemType", &(type->baseNs), NULL, &(type->base));
5504 /*
5505 * And now for the children...
5506 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005507 child = node->children;
5508 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005509 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5510 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005511 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005512 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005513 if (IS_SCHEMA(child, "simpleType")) {
5514 if (type->base != NULL) {
5515 xmlSchemaPCustomErr(ctxt,
5516 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5517 NULL, type, node,
5518 "The attribute 'itemType' and the <simpleType> child "
5519 "are mutually exclusive", NULL);
5520 } else {
5521 subtype = (xmlSchemaTypePtr)
5522 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5523 type->subtypes = subtype;
5524 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005525 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005526 }
5527 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005528 /* TODO: Think about the error code. */
5529 xmlSchemaPContentErr(ctxt,
5530 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5531 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005532 }
5533 return (type);
5534}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005535
Daniel Veillard4255d502002-04-16 15:50:10 +00005536/**
5537 * xmlSchemaParseSimpleType:
5538 * @ctxt: a schema validation context
5539 * @schema: the schema being built
5540 * @node: a subtree containing XML Schema informations
5541 *
5542 * parse a XML schema Simple Type definition
5543 * *WARNING* this interface is highly subject to change
5544 *
William M. Bracke7091952004-05-11 15:09:58 +00005545 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005547 */
5548static xmlSchemaTypePtr
5549xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005550 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005551{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005552 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005553 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 const xmlChar *attrValue = NULL;
5555 xmlChar *repName = NULL;
5556 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005557
5558 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5559 return (NULL);
5560
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005562
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 if (topLevel) {
5564 if (attr == NULL) {
5565 xmlSchemaPMissingAttrErr(ctxt,
5566 XML_SCHEMAP_S4S_ATTR_MISSING,
5567 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5568 "name", NULL);
5569 return (NULL);
5570 } else if (xmlSchemaPValAttrNode(ctxt,
5571 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5572 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005573 return (NULL);
5574 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575 }
5576
5577 if (topLevel == 0) {
5578 char buf[100];
5579
Daniel Veillard01fa6152004-06-29 17:04:39 +00005580 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005581 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005582 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005584 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005585 if (type == NULL)
5586 return (NULL);
5587 type->node = node;
5588 type->type = XML_SCHEMA_TYPE_SIMPLE;
5589 /*
5590 * Check for illegal attributes.
5591 */
5592 attr = node->properties;
5593 while (attr != NULL) {
5594 if (attr->ns == NULL) {
5595 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5596 xmlSchemaPIllegalAttrErr(ctxt,
5597 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5598 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005599 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005600 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5601 xmlSchemaPIllegalAttrErr(ctxt,
5602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5603 &repName, type, attr);
5604 }
5605 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005606 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005607 } else {
5608 /*
5609 * Parse as global simple type definition.
5610 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005611 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005612 if (type == NULL)
5613 return (NULL);
5614 type->node = node;
5615 type->type = XML_SCHEMA_TYPE_SIMPLE;
5616 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5617 /*
5618 * Check for illegal attributes.
5619 */
5620 attr = node->properties;
5621 while (attr != NULL) {
5622 if (attr->ns == NULL) {
5623 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5624 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5625 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5626 xmlSchemaPIllegalAttrErr(ctxt,
5627 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5628 &repName, type, attr);
5629 }
5630 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5631 xmlSchemaPIllegalAttrErr(ctxt,
5632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5633 &repName, type, attr);
5634 }
5635 attr = attr->next;
5636 }
5637 /*
5638 * Attribute "final".
5639 */
5640 attr = xmlSchemaGetPropNode(node, "final");
5641 if (attr == NULL) {
5642 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5643 } else {
5644 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5645 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5646 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5647 XML_SCHEMAS_TYPE_FINAL_LIST,
5648 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5649
5650 xmlSchemaPSimpleTypeErr(ctxt,
5651 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5652 &repName, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005653 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005654 attrValue, NULL, NULL, NULL);
5655 }
5656 }
5657 }
5658 /* TODO: Check id. */
5659 type->id = xmlSchemaGetProp(ctxt, node, "id");
5660 /*
5661 * And now for the children...
5662 */
5663 ctxtType = ctxt->ctxtType;
5664 ctxt->ctxtType = type;
5665 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005666 child = node->children;
5667 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005668 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5669 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005671 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005673 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005674 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005675 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005676 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005677 subtype = (xmlSchemaTypePtr)
5678 xmlSchemaParseList(ctxt, schema, child);
5679 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005681 subtype = (xmlSchemaTypePtr)
5682 xmlSchemaParseUnion(ctxt, schema, child);
5683 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005684 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005685 type->subtypes = subtype;
5686 if ((child != NULL) || (subtype == NULL)) {
5687 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5688 &repName, type, node, child, NULL,
5689 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005691 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005692 if (repName != NULL)
5693 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005694
Daniel Veillard4255d502002-04-16 15:50:10 +00005695 return (type);
5696}
5697
5698
5699/**
5700 * xmlSchemaParseGroup:
5701 * @ctxt: a schema validation context
5702 * @schema: the schema being built
5703 * @node: a subtree containing XML Schema informations
5704 *
5705 * parse a XML schema Group definition
5706 * *WARNING* this interface is highly subject to change
5707 *
William M. Bracke7091952004-05-11 15:09:58 +00005708 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005709 * 1 in case of success.
5710 */
5711static xmlSchemaTypePtr
5712xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005713 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005714{
5715 xmlSchemaTypePtr type, subtype;
5716 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005717 const xmlChar *name;
5718 const xmlChar *ref = NULL, *refNs = NULL;
5719 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005720 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005721
5722 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5723 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005724 /*
5725 * TODO: Validate the element even if no item is created
5726 * (i.e. min/maxOccurs == 0).
5727 */
5728 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5729 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5730 if ((minOccurs == 0) && (maxOccurs == 0)) {
5731 return (NULL);
5732 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005733 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005734 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005735 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5736 if (ref == NULL) {
5737 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 XML_SCHEMAP_GROUP_NONAME_NOREF,
5739 "Group definition or particle: One of the attributes \"name\" "
5740 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 return (NULL);
5742 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005743 if (refNs == NULL)
5744 refNs = schema->targetNamespace;
5745 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5746 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005747 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005748 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005749 if (type == NULL)
5750 return (NULL);
5751 type->node = node;
5752 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005753 if (topLevel)
5754 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005755 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005756 type->ref = ref;
5757 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005758 type->minOccurs = minOccurs;
5759 type->maxOccurs = maxOccurs;
5760 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005761 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005762
5763 child = node->children;
5764 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005765 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5766 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 }
5768 subtype = NULL;
5769 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005770 subtype = (xmlSchemaTypePtr)
5771 xmlSchemaParseAll(ctxt, schema, child);
5772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005773 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005774 subtype = xmlSchemaParseChoice(ctxt, schema, child);
5775 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005776 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005777 subtype = (xmlSchemaTypePtr)
5778 xmlSchemaParseSequence(ctxt, schema, child);
5779 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 }
5781 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005782 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005783 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005785 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005787 }
5788
5789 return (type);
5790}
5791
5792/**
5793 * xmlSchemaParseAll:
5794 * @ctxt: a schema validation context
5795 * @schema: the schema being built
5796 * @node: a subtree containing XML Schema informations
5797 *
5798 * parse a XML schema All definition
5799 * *WARNING* this interface is highly subject to change
5800 *
William M. Bracke7091952004-05-11 15:09:58 +00005801 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 * 1 in case of success.
5803 */
5804static xmlSchemaTypePtr
5805xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005807{
5808 xmlSchemaTypePtr type, subtype, last = NULL;
5809 xmlNodePtr child = NULL;
5810 xmlChar name[30];
5811
5812 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5813 return (NULL);
5814
5815
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005817 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005818 if (type == NULL)
5819 return (NULL);
5820 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00005821 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005822 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005823
5824 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
5825 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Daniel Veillard4255d502002-04-16 15:50:10 +00005826
5827 child = node->children;
5828 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005829 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5830 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 }
5832 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 subtype = (xmlSchemaTypePtr)
5834 xmlSchemaParseElement(ctxt, schema, child, 0);
5835 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00005836 if (subtype->minOccurs > 1)
5837 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005838 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005839 NULL, NULL);
5840 if (subtype->maxOccurs > 1)
5841 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005842 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005843 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005844 if (last == NULL) {
5845 type->subtypes = subtype;
5846 last = subtype;
5847 } else {
5848 last->next = subtype;
5849 last = subtype;
5850 }
5851 last->next = NULL;
5852 }
5853 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005854 }
5855 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005856 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005857 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 }
5860
5861 return (type);
5862}
5863
5864/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005865 * xmlSchemaCleanupDoc:
5866 * @ctxt: a schema validation context
5867 * @node: the root of the document.
5868 *
5869 * removes unwanted nodes in a schemas document tree
5870 */
5871static void
5872xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
5873{
5874 xmlNodePtr delete, cur;
5875
5876 if ((ctxt == NULL) || (root == NULL)) return;
5877
5878 /*
5879 * Remove all the blank text nodes
5880 */
5881 delete = NULL;
5882 cur = root;
5883 while (cur != NULL) {
5884 if (delete != NULL) {
5885 xmlUnlinkNode(delete);
5886 xmlFreeNode(delete);
5887 delete = NULL;
5888 }
5889 if (cur->type == XML_TEXT_NODE) {
5890 if (IS_BLANK_NODE(cur)) {
5891 if (xmlNodeGetSpacePreserve(cur) != 1) {
5892 delete = cur;
5893 }
5894 }
5895 } else if ((cur->type != XML_ELEMENT_NODE) &&
5896 (cur->type != XML_CDATA_SECTION_NODE)) {
5897 delete = cur;
5898 goto skip_children;
5899 }
5900
5901 /*
5902 * Skip to next node
5903 */
5904 if (cur->children != NULL) {
5905 if ((cur->children->type != XML_ENTITY_DECL) &&
5906 (cur->children->type != XML_ENTITY_REF_NODE) &&
5907 (cur->children->type != XML_ENTITY_NODE)) {
5908 cur = cur->children;
5909 continue;
5910 }
5911 }
5912 skip_children:
5913 if (cur->next != NULL) {
5914 cur = cur->next;
5915 continue;
5916 }
5917
5918 do {
5919 cur = cur->parent;
5920 if (cur == NULL)
5921 break;
5922 if (cur == root) {
5923 cur = NULL;
5924 break;
5925 }
5926 if (cur->next != NULL) {
5927 cur = cur->next;
5928 break;
5929 }
5930 } while (cur != NULL);
5931 }
5932 if (delete != NULL) {
5933 xmlUnlinkNode(delete);
5934 xmlFreeNode(delete);
5935 delete = NULL;
5936 }
5937}
5938
William M. Brack2f2a6632004-08-20 23:09:47 +00005939
5940/**
5941 * xmlSchemaImportSchema
5942 *
5943 * @ctxt: a schema validation context
5944 * @schemaLocation: an URI defining where to find the imported schema
5945 *
5946 * import a XML schema
5947 * *WARNING* this interface is highly subject to change
5948 *
5949 * Returns -1 in case of error and 1 in case of success.
5950 */
5951#if 0
5952static xmlSchemaImportPtr
5953xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
5954 const xmlChar *schemaLocation)
5955{
5956 xmlSchemaImportPtr import;
5957 xmlSchemaParserCtxtPtr newctxt;
5958
5959 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5960 if (newctxt == NULL) {
5961 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
5962 NULL);
5963 return (NULL);
5964 }
5965 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
5966 /* Keep the same dictionnary for parsing, really */
5967 xmlDictReference(ctxt->dict);
5968 newctxt->dict = ctxt->dict;
5969 newctxt->includes = 0;
5970 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
5971
5972 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
5973 ctxt->userData);
5974
5975 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
5976 if (import == NULL) {
5977 xmlSchemaPErrMemory(NULL, "allocating imported schema",
5978 NULL);
5979 xmlSchemaFreeParserCtxt(newctxt);
5980 return (NULL);
5981 }
5982
5983 memset(import, 0, sizeof(xmlSchemaImport));
5984 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
5985 import->schema = xmlSchemaParse(newctxt);
5986
5987 if (import->schema == NULL) {
5988 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005989 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00005990 "Failed to import schema from location \"%s\".\n",
5991 schemaLocation, NULL);
5992
5993 xmlSchemaFreeParserCtxt(newctxt);
5994 /* The schemaLocation is held by the dictionary.
5995 if (import->schemaLocation != NULL)
5996 xmlFree((xmlChar *)import->schemaLocation);
5997 */
5998 xmlFree(import);
5999 return NULL;
6000 }
6001
6002 xmlSchemaFreeParserCtxt(newctxt);
6003 return import;
6004}
6005#endif
6006
6007static void
6008xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6009{
6010 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6011 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6012
6013 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6014 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6015
6016 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6017 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6018 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6019 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6020 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6021 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6022 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6023 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6024
6025 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6026 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6027 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6028 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6029 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6030 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6031}
6032
6033static void
6034xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6035 xmlSchemaPtr schema,
6036 xmlNodePtr node)
6037{
6038 xmlAttrPtr attr;
6039 const xmlChar *val;
6040
6041 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6042 if (attr != NULL) {
6043 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6044 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6045 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6046 xmlSchemaPSimpleTypeErr(ctxt,
6047 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6048 NULL, NULL, (xmlNodePtr) attr, NULL,
6049 "(qualified | unqualified)", val, NULL, NULL, NULL);
6050 }
6051 }
6052
6053 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6054 if (attr != NULL) {
6055 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6056 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6057 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6058 xmlSchemaPSimpleTypeErr(ctxt,
6059 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6060 NULL, NULL, (xmlNodePtr) attr, NULL,
6061 "(qualified | unqualified)", val, NULL, NULL, NULL);
6062 }
6063 }
6064
6065 attr = xmlSchemaGetPropNode(node, "finalDefault");
6066 if (attr != NULL) {
6067 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6068 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6069 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6070 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6071 -1,
6072 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6073 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6074 xmlSchemaPSimpleTypeErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076 NULL, NULL, (xmlNodePtr) attr, NULL,
6077 "(#all | List of (extension | restriction | list | union))",
6078 val, NULL, NULL, NULL);
6079 }
6080 }
6081
6082 attr = xmlSchemaGetPropNode(node, "blockDefault");
6083 if (attr != NULL) {
6084 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6085 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6086 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6087 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6088 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6089 xmlSchemaPSimpleTypeErr(ctxt,
6090 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6091 NULL, NULL, (xmlNodePtr) attr, NULL,
6092 "(#all | List of (extension | restriction | substitution))",
6093 val, NULL, NULL, NULL);
6094 }
6095 }
6096}
6097
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006098/**
6099 * xmlSchemaParseSchemaTopLevel:
6100 * @ctxt: a schema validation context
6101 * @schema: the schemas
6102 * @nodes: the list of top level nodes
6103 *
6104 * Returns the internal XML Schema structure built from the resource or
6105 * NULL in case of error
6106 */
6107static void
6108xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6109 xmlSchemaPtr schema, xmlNodePtr nodes)
6110{
6111 xmlNodePtr child;
6112 xmlSchemaAnnotPtr annot;
6113
6114 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6115 return;
6116
6117 child = nodes;
6118 while ((IS_SCHEMA(child, "include")) ||
6119 (IS_SCHEMA(child, "import")) ||
6120 (IS_SCHEMA(child, "redefine")) ||
6121 (IS_SCHEMA(child, "annotation"))) {
6122 if (IS_SCHEMA(child, "annotation")) {
6123 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6124 if (schema->annot == NULL)
6125 schema->annot = annot;
6126 else
6127 xmlSchemaFreeAnnot(annot);
6128 } else if (IS_SCHEMA(child, "import")) {
6129 xmlSchemaParseImport(ctxt, schema, child);
6130 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006131 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006132 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006133 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006134 } else if (IS_SCHEMA(child, "redefine")) {
6135 TODO
6136 }
6137 child = child->next;
6138 }
6139 while (child != NULL) {
6140 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006141 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006142 child = child->next;
6143 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006144 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006145 child = child->next;
6146 } else if (IS_SCHEMA(child, "element")) {
6147 xmlSchemaParseElement(ctxt, schema, child, 1);
6148 child = child->next;
6149 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006150 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006151 child = child->next;
6152 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006153 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006154 child = child->next;
6155 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006156 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006157 child = child->next;
6158 } else if (IS_SCHEMA(child, "notation")) {
6159 xmlSchemaParseNotation(ctxt, schema, child);
6160 child = child->next;
6161 } else {
6162 xmlSchemaPErr2(ctxt, NULL, child,
6163 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006164 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006165 child->name, NULL);
6166 child = child->next;
6167 }
6168 while (IS_SCHEMA(child, "annotation")) {
6169 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6170 if (schema->annot == NULL)
6171 schema->annot = annot;
6172 else
6173 xmlSchemaFreeAnnot(annot);
6174 child = child->next;
6175 }
6176 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006177 ctxt->parentItem = NULL;
6178 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006179}
6180
William M. Brack2f2a6632004-08-20 23:09:47 +00006181
6182/**
6183 * xmlSchemaParseImport:
6184 * @ctxt: a schema validation context
6185 * @schema: the schema being built
6186 * @node: a subtree containing XML Schema informations
6187 *
6188 * parse a XML schema Import definition
6189 * *WARNING* this interface is highly subject to change
6190 *
6191 * Returns 0 in case of success, a positive error code if
6192 * not valid and -1 in case of an internal error.
6193 */
6194static int
6195xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6196 xmlNodePtr node)
6197{
6198 xmlNodePtr child = NULL;
6199 xmlSchemaImportPtr import = NULL;
6200 const xmlChar *namespace = NULL, *ns;
6201 const xmlChar *schemaLocation = NULL;
6202 const xmlChar *targetNamespace, *oldTNS, *url;
6203 xmlAttrPtr attr;
6204 xmlDocPtr doc;
6205 xmlNodePtr root;
6206 xmlChar *base = NULL;
6207 xmlChar *URI = NULL;
6208 int flags;
6209 xmlParserCtxtPtr parserCtxt;
6210
6211
6212 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6213 return (-1);
6214
6215 /*
6216 * Check for illegal attributes.
6217 */
6218 attr = node->properties;
6219 while (attr != NULL) {
6220 if (attr->ns == NULL) {
6221 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6222 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6223 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6224 xmlSchemaPIllegalAttrErr(ctxt,
6225 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6226 NULL, NULL, attr);
6227 }
6228 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6229 xmlSchemaPIllegalAttrErr(ctxt,
6230 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6231 NULL, NULL, attr);
6232 }
6233 attr = attr->next;
6234 }
6235 /*
6236 * Extract and validate attributes.
6237 */
6238 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6239 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6240 &namespace) != 0) {
6241 xmlSchemaPSimpleTypeErr(ctxt,
6242 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6243 NULL, NULL, node,
6244 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6245 NULL, namespace, NULL, NULL, NULL);
6246 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6247 }
6248
6249 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6250 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6251 &schemaLocation) != 0) {
6252 xmlSchemaPSimpleTypeErr(ctxt,
6253 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6254 NULL, NULL, node,
6255 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6256 NULL, namespace, NULL, NULL, NULL);
6257 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6258 }
6259 /*
6260 * And now for the children...
6261 */
6262 child = node->children;
6263 if (IS_SCHEMA(child, "annotation")) {
6264 /*
6265 * the annotation here is simply discarded ...
6266 */
6267 child = child->next;
6268 }
6269 if (child != NULL) {
6270 xmlSchemaPContentErr(ctxt,
6271 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6272 NULL, NULL, node, child, NULL,
6273 "(annotation?)");
6274 }
6275 /*
6276 * Apply additional constraints.
6277 */
6278 if (namespace != NULL) {
6279 /*
6280 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6281 * must not match the ·actual value· of the enclosing <schema>'s
6282 * targetNamespace [attribute].
6283 */
6284 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6285 xmlSchemaPCustomErr(ctxt,
6286 XML_SCHEMAP_SRC_IMPORT_1_1,
6287 NULL, NULL, node,
6288 "The value of the attribute 'namespace' must not match "
6289 "the target namespace '%s' of the importing schema",
6290 schema->targetNamespace);
6291 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6292 }
6293 } else {
6294 /*
6295 * 1.2 If the namespace [attribute] is not present, then the enclosing
6296 * <schema> must have a targetNamespace [attribute].
6297 */
6298 if (schema->targetNamespace == NULL) {
6299 xmlSchemaPCustomErr(ctxt,
6300 XML_SCHEMAP_SRC_IMPORT_1_2,
6301 NULL, NULL, node,
6302 "The attribute 'namespace' must be existent if "
6303 "the importing schema has no target namespace",
6304 NULL);
6305 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6306 }
6307 }
6308
6309 /*
6310 * Given that the schemaLocation [attribute] is only a hint, it is open
6311 * to applications to ignore all but the first <import> for a given
6312 * namespace, regardless of the ·actual value· of schemaLocation, but
6313 * such a strategy risks missing useful information when new
6314 * schemaLocations are offered.
6315 *
6316 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6317 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6318 * valid or not.
6319 * We will follow XSV here.
6320 */
6321 if (schemaLocation == NULL) {
6322 /*
6323 * Schema Document Location Strategy:
6324 *
6325 * 3 Based on the namespace name, identify an existing schema document,
6326 * either as a resource which is an XML document or a <schema> element
6327 * information item, in some local schema repository;
6328 *
6329 * 5 Attempt to resolve the namespace name to locate such a resource.
6330 *
6331 * NOTE: Those stategies are not supported, so we will skip.
6332 */
6333 return (0);
6334 }
6335 if (namespace == NULL)
6336 ns = XML_SCHEMAS_NO_NAMESPACE;
6337 else
6338 ns = namespace;
6339
6340 import = xmlHashLookup(schema->schemasImports, ns);
6341 if (import != NULL) {
6342 /*
6343 * There was a valid resource for the specified namespace already
6344 * defined, so skip.
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006345 * TODO: This might be changed someday to allow import of
6346 * components from multiple documents for a single target namespace.
William M. Brack2f2a6632004-08-20 23:09:47 +00006347 */
6348 return (0);
6349 }
6350 /*
6351 * Schema Document Location Strategy:
6352 *
6353 * 2 Based on the location URI, identify an existing schema document,
6354 * either as a resource which is an XML document or a <schema> element
6355 * information item, in some local schema repository;
6356 *
6357 * 4 Attempt to resolve the location URI, to locate a resource on the
6358 * web which is or contains or references a <schema> element;
6359 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6360 *
6361 */
6362
6363 base = xmlNodeGetBase(node->doc, node);
6364 if (base == NULL) {
6365 URI = xmlBuildURI(schemaLocation, node->doc->URL);
6366 } else {
6367 URI = xmlBuildURI(schemaLocation, base);
6368 xmlFree(base);
6369 }
6370 if (URI != NULL) {
6371 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
6372 xmlFree(URI);
6373 }
6374
6375 parserCtxt = xmlNewParserCtxt();
6376 if (parserCtxt == NULL) {
6377 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6378 "allocating a parser context", NULL);
6379 return(-1);
6380 }
6381
6382 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
6383 NULL, SCHEMAS_PARSE_OPTIONS);
6384
6385 /*
6386 * 2.1 The referent is (a fragment of) a resource which is an
6387 * XML document (see clause 1.1), which in turn corresponds to
6388 * a <schema> element information item in a well-formed information
6389 * set, which in turn corresponds to a valid schema.
6390 * TODO: What to do with the "fragment" stuff?
6391 *
6392 * 2.2 The referent is a <schema> element information item in
6393 * a well-formed information set, which in turn corresponds
6394 * to a valid schema.
6395 * NOTE: 2.2 won't apply, since only XML documents will be processed
6396 * here.
6397 */
6398 if (doc == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006399 xmlErrorPtr lerr;
William M. Brack2f2a6632004-08-20 23:09:47 +00006400 /*
6401 * It is *not* an error for the application schema reference
6402 * strategy to fail.
6403 *
6404 * If the doc is NULL and the parser error is an IO error we
6405 * will assume that the resource could not be located or accessed.
6406 *
6407 * TODO: Try to find specific error codes to react only on
6408 * localisation failures.
6409 *
6410 * TODO, FIXME: Check the spec: is a namespace added to the imported
6411 * namespaces, even if the schemaLocation did not provide
6412 * a resource? I guess so, since omitting the "schemaLocation"
6413 * attribute, imports a namespace as well.
6414 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006415 lerr = xmlGetLastError();
6416 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006417 xmlFreeParserCtxt(parserCtxt);
6418 return(0);
6419 }
6420
6421 xmlSchemaPCustomErr(ctxt,
6422 XML_SCHEMAP_SRC_IMPORT_2_1,
6423 NULL, NULL, node,
6424 "Failed to parse the resource '%s' for import",
6425 schemaLocation);
6426 xmlFreeParserCtxt(parserCtxt);
6427 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6428 }
6429 xmlFreeParserCtxt(parserCtxt);
6430
6431 root = xmlDocGetRootElement(doc);
6432 if (root == NULL) {
6433 xmlSchemaPCustomErr(ctxt,
6434 XML_SCHEMAP_SRC_IMPORT_2_1,
6435 NULL, NULL, node,
6436 "The XML document '%s' to be imported has no document "
6437 "element", schemaLocation);
6438 xmlFreeDoc(doc);
6439 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6440 }
6441
6442 xmlSchemaCleanupDoc(ctxt, root);
6443
6444 if (!IS_SCHEMA(root, "schema")) {
6445 xmlSchemaPCustomErr(ctxt,
6446 XML_SCHEMAP_SRC_IMPORT_2_1,
6447 NULL, NULL, node,
6448 "The XML document '%s' to be imported is not a XML schema document",
6449 schemaLocation);
6450 xmlFreeDoc(doc);
6451 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6452 }
6453 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6454 /*
6455 * Schema Representation Constraint: Import Constraints and Semantics
6456 */
6457 if (namespace == NULL) {
6458 if (targetNamespace != NULL) {
6459 xmlSchemaPCustomErr(ctxt,
6460 XML_SCHEMAP_SRC_IMPORT_3_2,
6461 NULL, NULL, node,
6462 "No 'namespace' attribute was "
6463 "specified, thus the XML schema to be imported "
6464 "must have no target namespace", NULL);
6465 xmlFreeDoc(doc);
6466 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6467 }
6468 } else {
6469 if (targetNamespace == NULL) {
6470 xmlSchemaPCustomErr(ctxt,
6471 XML_SCHEMAP_SRC_IMPORT_3_1,
6472 NULL, NULL, node,
6473 "The attribute 'namespace' requires the XML schema to be "
6474 "imported to have a target namespace of '%s'", namespace);
6475 xmlFreeDoc(doc);
6476 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6477 } else if (!xmlStrEqual(targetNamespace, namespace)) {
6478 xmlSchemaPCustomErrExt(ctxt,
6479 XML_SCHEMAP_SRC_IMPORT_3_1,
6480 NULL, NULL, node,
6481 "The value '%s' of the attribute 'namespace' is not "
6482 "identical to the target namespace '%s' of the "
6483 "XML schema to be imported",
6484 namespace, targetNamespace, NULL);
6485 xmlFreeDoc(doc);
6486 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6487 }
6488 }
6489 /*
6490 * Finally, import the schema.
6491 */
6492 if (schema->schemasImports == NULL) {
6493 schema->schemasImports = xmlHashCreate(10);
6494 if (schema->schemasImports == NULL) {
6495 xmlSchemaPErr2(ctxt, node, child,
6496 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6497 "Internal error: failed to build import table.\n",
6498 NULL, NULL);
6499 return (-1);
6500 }
6501 }
6502 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6503 if (import == NULL) {
6504 xmlSchemaPErrMemory(NULL, "allocating imported schema", NULL);
6505 xmlFreeDoc(doc);
6506 return (-1);
6507 }
6508 memset(import, 0, sizeof(xmlSchemaImport));
6509 import->schemaLocation = schemaLocation;
6510 import->doc = doc;
6511 xmlHashAddEntry(schema->schemasImports, ns, import);
6512 /*
6513 * Save and reset the context & schema.
6514 */
6515 url = ctxt->URL;
6516 /* TODO: Check this. */
6517 ctxt->URL = schemaLocation;
6518 flags = schema->flags;
6519 oldTNS = schema->targetNamespace;
6520
6521 xmlSchemaClearSchemaDefaults(schema);
6522 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6523 schema->targetNamespace = targetNamespace;
6524 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6525
6526 /*
6527 * Restore the context & schema.
6528 */
6529 schema->flags = flags;
6530 schema->targetNamespace = oldTNS;
6531 ctxt->URL = url;
6532
6533 return (1);
6534}
6535
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006536/**
6537 * xmlSchemaParseInclude:
6538 * @ctxt: a schema validation context
6539 * @schema: the schema being built
6540 * @node: a subtree containing XML Schema informations
6541 *
6542 * parse a XML schema Include definition
6543 *
William M. Bracke7091952004-05-11 15:09:58 +00006544 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006545 * 1 in case of success.
6546 */
6547static int
6548xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6549 xmlNodePtr node)
6550{
6551 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006553 xmlDocPtr doc;
6554 xmlNodePtr root;
6555 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006557 xmlAttrPtr attr;
6558 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006559
6560
6561 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6562 return (-1);
6563
6564 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006565 * Check for illegal attributes.
6566 */
6567 attr = node->properties;
6568 while (attr != NULL) {
6569 if (attr->ns == NULL) {
6570 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6571 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6572 xmlSchemaPIllegalAttrErr(ctxt,
6573 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6574 NULL, NULL, attr);
6575 }
6576 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6577 xmlSchemaPIllegalAttrErr(ctxt,
6578 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6579 NULL, NULL, attr);
6580 }
6581 attr = attr->next;
6582 }
6583 /*
6584 * Extract and validate attributes.
6585 */
6586 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006587 * Preliminary step, extract the URI-Reference for the include and
6588 * make an URI from the base.
6589 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006590 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6591 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006592 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006593 xmlChar *uri = NULL;
6594
6595 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6596 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6597 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006598 base = xmlNodeGetBase(node->doc, node);
6599 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006600 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006601 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006602 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006603 xmlFree(base);
6604 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006605 if (uri != NULL) {
6606 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6607 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006608 }
6609 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006610 xmlSchemaPMissingAttrErr(ctxt,
6611 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6612 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006613 return (-1);
6614 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006615 /*
6616 * And now for the children...
6617 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006618 child = node->children;
6619 while (IS_SCHEMA(child, "annotation")) {
6620 /*
6621 * the annotations here are simply discarded ...
6622 */
6623 child = child->next;
6624 }
6625 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006626 xmlSchemaPContentErr(ctxt,
6627 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6628 NULL, NULL, node, child, NULL,
6629 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006630 }
6631
6632 /*
6633 * First step is to parse the input document into an DOM/Infoset
6634 */
6635 doc = xmlReadFile((const char *) schemaLocation, NULL,
6636 SCHEMAS_PARSE_OPTIONS);
6637 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006638 /*
6639 * TODO: It is not an error for the ·actual value· of the
6640 * schemaLocation [attribute] to fail to resolve it all, in which
6641 * case no corresponding inclusion is performed.
6642 * So do we need a warning report here?
6643 */
6644 xmlSchemaPCustomErr(ctxt,
6645 XML_SCHEMAP_FAILED_LOAD,
6646 NULL, NULL, node,
6647 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006648 return(-1);
6649 }
6650
6651 /*
6652 * Then extract the root of the schema
6653 */
6654 root = xmlDocGetRootElement(doc);
6655 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006656 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006657 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006658 NULL, NULL, node,
6659 "The included document '%s' has no document "
6660 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006661 xmlFreeDoc(doc);
6662 return (-1);
6663 }
6664
6665 /*
6666 * Remove all the blank text nodes
6667 */
6668 xmlSchemaCleanupDoc(ctxt, root);
6669
6670 /*
6671 * Check the schemas top level element
6672 */
6673 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006674 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006675 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006676 NULL, NULL, node,
6677 "The document '%s' to be included is not a schema document",
6678 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006679 xmlFreeDoc(doc);
6680 return (-1);
6681 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006682
William M. Brack2f2a6632004-08-20 23:09:47 +00006683 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006684 /*
6685 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6686 * value· is identical to the ·actual value· of the targetNamespace
6687 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6688 */
6689 if (targetNamespace != NULL) {
6690 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006691 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006692 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006693 NULL, NULL, node,
6694 "The target namespace of the included schema "
6695 "'%s' has to be absent, since the including schema "
6696 "has no target namespace",
6697 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006698 xmlFreeDoc(doc);
6699 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006700 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6701 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006702 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006703 NULL, NULL, node,
6704 "The target namespace '%s' of the included schema '%s' "
6705 "differs from '%s' of the including schema",
6706 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006707 xmlFreeDoc(doc);
6708 return (-1);
6709 }
6710 } else if (schema->targetNamespace != NULL) {
6711 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
6712 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
6713 } else
6714 wasConvertingNs = 1;
6715 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006716 /*
6717 * register the include
6718 */
6719 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
6720 if (include == NULL) {
6721 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
6722 xmlFreeDoc(doc);
6723 return (-1);
6724 }
6725
6726 memset(include, 0, sizeof(xmlSchemaInclude));
6727 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6728 include->doc = doc;
6729 include->next = schema->includes;
6730 schema->includes = include;
6731
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006732 /*
6733 * parse the declarations in the included file like if they
6734 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 */
6736 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006737 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006739 /*
6740 * The default values ("blockDefault", "elementFormDefault", etc.)
6741 * are set to the values of the included schema and restored afterwards.
6742 */
6743 saveFlags = schema->flags;
6744 xmlSchemaClearSchemaDefaults(schema);
6745 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006746 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00006747 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 /*
6749 * Remove the converting flag.
6750 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006751 if ((wasConvertingNs == 0) &&
6752 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006753 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006754 return (1);
6755}
6756
6757/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006758 * xmlSchemaParseChoice:
6759 * @ctxt: a schema validation context
6760 * @schema: the schema being built
6761 * @node: a subtree containing XML Schema informations
6762 *
6763 * parse a XML schema Choice definition
6764 * *WARNING* this interface is highly subject to change
6765 *
William M. Bracke7091952004-05-11 15:09:58 +00006766 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006767 * 1 in case of success.
6768 */
6769static xmlSchemaTypePtr
6770xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006771 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006772{
6773 xmlSchemaTypePtr type, subtype, last = NULL;
6774 xmlNodePtr child = NULL;
6775 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006776 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006777
6778 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6779 return (NULL);
6780
6781
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006782 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006783 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006784 if (type == NULL)
6785 return (NULL);
6786 type->node = node;
6787 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006788 /*
6789 * Check for illegal attributes.
6790 */
6791 attr = node->properties;
6792 while (attr != NULL) {
6793 if (attr->ns == NULL) {
6794 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6795 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6796 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6797 xmlSchemaPIllegalAttrErr(ctxt,
6798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6799 NULL, type, attr);
6800 }
6801 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6802 xmlSchemaPIllegalAttrErr(ctxt,
6803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6804 NULL, type, attr);
6805 }
6806 attr = attr->next;
6807 }
6808 /*
6809 * Extract and validate attributes.
6810 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006811 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006812 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6813 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6814 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00006815 /*
6816 * And now for the children...
6817 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006818 child = node->children;
6819 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006820 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6821 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006822 }
6823 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006824 (IS_SCHEMA(child, "group")) ||
6825 (IS_SCHEMA(child, "any")) ||
6826 (IS_SCHEMA(child, "choice")) ||
6827 (IS_SCHEMA(child, "sequence"))) {
6828 subtype = NULL;
6829 if (IS_SCHEMA(child, "element")) {
6830 subtype = (xmlSchemaTypePtr)
6831 xmlSchemaParseElement(ctxt, schema, child, 0);
6832 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006833 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006834 } else if (IS_SCHEMA(child, "any")) {
6835 subtype = xmlSchemaParseAny(ctxt, schema, child);
6836 } else if (IS_SCHEMA(child, "sequence")) {
6837 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6838 } else if (IS_SCHEMA(child, "choice")) {
6839 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6840 }
6841 if (subtype != NULL) {
6842 if (last == NULL) {
6843 type->subtypes = subtype;
6844 last = subtype;
6845 } else {
6846 last->next = subtype;
6847 last = subtype;
6848 }
6849 last->next = NULL;
6850 }
6851 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006852 }
6853 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006854 /* TODO: error code. */
6855 xmlSchemaPContentErr(ctxt,
6856 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
6857 NULL, type, node, child, NULL,
6858 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006859 }
6860
6861 return (type);
6862}
6863
6864/**
6865 * xmlSchemaParseSequence:
6866 * @ctxt: a schema validation context
6867 * @schema: the schema being built
6868 * @node: a subtree containing XML Schema informations
6869 *
6870 * parse a XML schema Sequence definition
6871 * *WARNING* this interface is highly subject to change
6872 *
William M. Bracke7091952004-05-11 15:09:58 +00006873 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006874 * 1 in case of success.
6875 */
6876static xmlSchemaTypePtr
6877xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006878 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006879{
6880 xmlSchemaTypePtr type, subtype, last = NULL;
6881 xmlNodePtr child = NULL;
6882 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006883 xmlAttrPtr attr;
6884 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006885
6886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6887 return (NULL);
6888
William M. Brack2f2a6632004-08-20 23:09:47 +00006889 oldcontainer = ctxt->container;
6890 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
6891 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006892 if (type == NULL)
6893 return (NULL);
6894 type->node = node;
6895 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006896 /*
6897 * Check for illegal attributes.
6898 */
6899 attr = node->properties;
6900 while (attr != NULL) {
6901 if (attr->ns == NULL) {
6902 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6903 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6904 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6905 xmlSchemaPIllegalAttrErr(ctxt,
6906 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6907 NULL, type, attr);
6908 }
6909 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6910 xmlSchemaPIllegalAttrErr(ctxt,
6911 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6912 NULL, type, attr);
6913 }
6914 attr = attr->next;
6915 }
6916 /*
6917 * Extract and validate attributes.
6918 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006919 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006920 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6921 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6922 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 /*
6924 * And now for the children...
6925 */
6926 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006927 child = node->children;
6928 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006929 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6930 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006931 }
6932 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006933 (IS_SCHEMA(child, "group")) ||
6934 (IS_SCHEMA(child, "any")) ||
6935 (IS_SCHEMA(child, "choice")) ||
6936 (IS_SCHEMA(child, "sequence"))) {
6937 subtype = NULL;
6938 if (IS_SCHEMA(child, "element")) {
6939 subtype = (xmlSchemaTypePtr)
6940 xmlSchemaParseElement(ctxt, schema, child, 0);
6941 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006942 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006943 } else if (IS_SCHEMA(child, "any")) {
6944 subtype = xmlSchemaParseAny(ctxt, schema, child);
6945 } else if (IS_SCHEMA(child, "choice")) {
6946 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6947 } else if (IS_SCHEMA(child, "sequence")) {
6948 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6949 }
6950 if (subtype != NULL) {
6951 if (last == NULL) {
6952 type->subtypes = subtype;
6953 last = subtype;
6954 } else {
6955 last->next = subtype;
6956 last = subtype;
6957 }
6958 last->next = NULL;
6959 }
6960 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006961 }
6962 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006963 xmlSchemaPContentErr(ctxt,
6964 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
6965 NULL, type, node, child, NULL,
6966 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006968 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006969
6970 return (type);
6971}
6972
6973/**
6974 * xmlSchemaParseRestriction:
6975 * @ctxt: a schema validation context
6976 * @schema: the schema being built
6977 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00006978 *
6979 * parse a XML schema Restriction definition
6980 * *WARNING* this interface is highly subject to change
6981 *
6982 * Returns the type definition or NULL in case of error
6983 */
6984static xmlSchemaTypePtr
6985xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006986 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006987{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006988 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006989 xmlNodePtr child = NULL;
6990 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006991 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00006992 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006993
6994 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6995 return (NULL);
6996
6997 oldcontainer = ctxt->container;
6998
William M. Brack2f2a6632004-08-20 23:09:47 +00006999 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7000 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007001 if (type == NULL)
7002 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007003 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007004 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007005 /*
7006 * Check for illegal attributes.
7007 */
7008 attr = node->properties;
7009 while (attr != NULL) {
7010 if (attr->ns == NULL) {
7011 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7012 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7013 xmlSchemaPIllegalAttrErr(ctxt,
7014 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7015 NULL, type, attr);
7016 }
7017 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7018 xmlSchemaPIllegalAttrErr(ctxt,
7019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7020 NULL, type, attr);
7021 }
7022 attr = attr->next;
7023 }
7024 /*
7025 * Extract and validate attributes.
7026 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007027 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007028 /*
7029 * Attribute "base".
7030 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007031 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007032 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007033 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7034 /* TODO: Think about the error code. */
7035 xmlSchemaPMissingAttrErr(ctxt,
7036 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7037 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007038 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007039 /*
7040 * And now for the children...
7041 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007043 child = node->children;
7044 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007045 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7046 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 }
7048 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007049 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7050 if (IS_SCHEMA(child, "all")) {
7051 subtype = (xmlSchemaTypePtr)
7052 xmlSchemaParseAll(ctxt, schema, child);
7053 child = child->next;
7054 type->subtypes = subtype;
7055 } else if (IS_SCHEMA(child, "choice")) {
7056 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7057 child = child->next;
7058 type->subtypes = subtype;
7059 } else if (IS_SCHEMA(child, "sequence")) {
7060 subtype = (xmlSchemaTypePtr)
7061 xmlSchemaParseSequence(ctxt, schema, child);
7062 child = child->next;
7063 type->subtypes = subtype;
7064 } else if (IS_SCHEMA(child, "group")) {
7065 subtype = (xmlSchemaTypePtr)
7066 xmlSchemaParseGroup(ctxt, schema, child, 0);
7067 child = child->next;
7068 type->subtypes = subtype;
7069 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007070 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7071 if (IS_SCHEMA(child, "simpleType")) {
7072 if (type->base != NULL) {
7073 /*
7074 * src-restriction-base-or-simpleType
7075 * Either the base [attribute] or the simpleType [child] of the
7076 * <restriction> element must be present, but not both.
7077 */
7078 xmlSchemaPContentErr(ctxt,
7079 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7080 NULL, NULL, type->node, child,
7081 "The attribute 'base' and the <simpleType> child are "
7082 "mutually exclusive", NULL);
7083 } else {
7084 subtype = (xmlSchemaTypePtr)
7085 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7086 type->baseType = subtype;
7087 }
7088 child = child->next;
7089 }
7090 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007091 if (IS_SCHEMA(child, "simpleType")) {
7092 subtype = (xmlSchemaTypePtr)
7093 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007094 type->subtypes = subtype;
7095 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007096 }
7097 }
7098 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7099 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7100 xmlSchemaFacetPtr facet, lastfacet = NULL;
7101
Daniel Veillard01fa6152004-06-29 17:04:39 +00007102 /*
7103 * Add the facets to the parent simpleType/complexType.
7104 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007105 /*
7106 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7107 * Simple Type Definition Schema Representation Constraint:
7108 * *Single Facet Value*
7109 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007110 while ((IS_SCHEMA(child, "minInclusive")) ||
7111 (IS_SCHEMA(child, "minExclusive")) ||
7112 (IS_SCHEMA(child, "maxInclusive")) ||
7113 (IS_SCHEMA(child, "maxExclusive")) ||
7114 (IS_SCHEMA(child, "totalDigits")) ||
7115 (IS_SCHEMA(child, "fractionDigits")) ||
7116 (IS_SCHEMA(child, "pattern")) ||
7117 (IS_SCHEMA(child, "enumeration")) ||
7118 (IS_SCHEMA(child, "whiteSpace")) ||
7119 (IS_SCHEMA(child, "length")) ||
7120 (IS_SCHEMA(child, "maxLength")) ||
7121 (IS_SCHEMA(child, "minLength"))) {
7122 facet = xmlSchemaParseFacet(ctxt, schema, child);
7123 if (facet != NULL) {
7124 if (lastfacet == NULL)
7125 ctxt->ctxtType->facets = facet;
7126 else
7127 lastfacet->next = facet;
7128 lastfacet = facet;
7129 lastfacet->next = NULL;
7130 }
7131 child = child->next;
7132 }
7133 /*
7134 * Create links for derivation and validation.
7135 */
7136 if (lastfacet != NULL) {
7137 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7138
7139 facet = ctxt->ctxtType->facets;
7140 do {
7141 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7142 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007143 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007144 xmlFree(facetLink);
7145 return (NULL);
7146 }
7147 facetLink->facet = facet;
7148 facetLink->next = NULL;
7149 if (lastFacetLink == NULL)
7150 ctxt->ctxtType->facetSet = facetLink;
7151 else
7152 lastFacetLink->next = facetLink;
7153 lastFacetLink = facetLink;
7154 facet = facet->next;
7155 } while (facet != NULL);
7156 }
7157 }
7158 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
William M. Brack2f2a6632004-08-20 23:09:47 +00007159 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007160 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007161 /* TODO: Think about the error code. */
7162 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7163 xmlSchemaPContentErr(ctxt,
7164 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7165 NULL, type, node, child, NULL,
7166 "annotation?, (group | all | choice | sequence)?, "
7167 "((attribute | attributeGroup)*, anyAttribute?))");
7168 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7169 xmlSchemaPContentErr(ctxt,
7170 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7171 NULL, type, node, child, NULL,
7172 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7173 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7174 "length | minLength | maxLength | enumeration | whiteSpace | "
7175 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7176 } else {
7177 /* Simple type */
7178 xmlSchemaPContentErr(ctxt,
7179 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7180 NULL, type, node, child, NULL,
7181 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7182 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7183 "length | minLength | maxLength | enumeration | whiteSpace | "
7184 "pattern)*))");
7185 }
7186 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007187 ctxt->container = oldcontainer;
7188 return (type);
7189}
7190
7191/**
7192 * xmlSchemaParseExtension:
7193 * @ctxt: a schema validation context
7194 * @schema: the schema being built
7195 * @node: a subtree containing XML Schema informations
7196 *
7197 * parse a XML schema Extension definition
7198 * *WARNING* this interface is highly subject to change
7199 *
7200 * Returns the type definition or NULL in case of error
7201 */
7202static xmlSchemaTypePtr
7203xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007204 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007205{
7206 xmlSchemaTypePtr type, subtype;
7207 xmlNodePtr child = NULL;
7208 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007209 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007210
7211 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7212 return (NULL);
7213
7214 oldcontainer = ctxt->container;
7215
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007216 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007217 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007218 if (type == NULL)
7219 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007220 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007222 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007223 ctxt->container = name;
7224
7225 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7226 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007227 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007228 "<extension>: The attribute \"base\" is missing.\n",
7229 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007230 }
7231 child = node->children;
7232 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7234 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007235 }
7236 subtype = NULL;
7237
7238 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007239 subtype = xmlSchemaParseAll(ctxt, schema, child);
7240 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007241 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007242 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7243 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007244 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007245 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007247 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007248 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007249 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007250 }
7251 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007252 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007253 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7254 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007255 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007256 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7257 "<extension> has unexpected content.\n", type->name,
7258 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007259 }
7260 ctxt->container = oldcontainer;
7261 return (type);
7262}
7263
7264/**
7265 * xmlSchemaParseSimpleContent:
7266 * @ctxt: a schema validation context
7267 * @schema: the schema being built
7268 * @node: a subtree containing XML Schema informations
7269 *
7270 * parse a XML schema SimpleContent definition
7271 * *WARNING* this interface is highly subject to change
7272 *
7273 * Returns the type definition or NULL in case of error
7274 */
7275static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007276xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7277 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007278{
7279 xmlSchemaTypePtr type, subtype;
7280 xmlNodePtr child = NULL;
7281 xmlChar name[30];
7282
7283 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7284 return (NULL);
7285
William M. Bracke7091952004-05-11 15:09:58 +00007286 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007287 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007288 if (type == NULL)
7289 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007290 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007291 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007292 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007293
7294 child = node->children;
7295 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007296 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7297 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007298 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007299 ctxt->parentItem = type;
7300 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007301 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007302 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007303 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007305 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007306 subtype = (xmlSchemaTypePtr)
7307 xmlSchemaParseExtension(ctxt, schema, child);
7308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007309 }
7310 type->subtypes = subtype;
7311 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007312 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007313 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7314 "<simpleContent> has unexpected content.\n",
7315 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007316 }
7317 return (type);
7318}
7319
7320/**
7321 * xmlSchemaParseComplexContent:
7322 * @ctxt: a schema validation context
7323 * @schema: the schema being built
7324 * @node: a subtree containing XML Schema informations
7325 *
7326 * parse a XML schema ComplexContent definition
7327 * *WARNING* this interface is highly subject to change
7328 *
7329 * Returns the type definition or NULL in case of error
7330 */
7331static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007332xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7333 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007334{
7335 xmlSchemaTypePtr type, subtype;
7336 xmlNodePtr child = NULL;
7337 xmlChar name[30];
7338
7339 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7340 return (NULL);
7341
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007342 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007343 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007344 if (type == NULL)
7345 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007346 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007347 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007348 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007349
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->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007356 subtype = NULL;
7357 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007358 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007359 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007360 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007361 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007362 subtype = (xmlSchemaTypePtr)
7363 xmlSchemaParseExtension(ctxt, schema, child);
7364 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007365 }
7366 type->subtypes = subtype;
7367 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007368 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007369 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
7370 "<complexContent> has unexpected content.\n",
7371 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007372 }
7373 return (type);
7374}
7375
7376/**
7377 * xmlSchemaParseComplexType:
7378 * @ctxt: a schema validation context
7379 * @schema: the schema being built
7380 * @node: a subtree containing XML Schema informations
7381 *
7382 * parse a XML schema Complex Type definition
7383 * *WARNING* this interface is highly subject to change
7384 *
7385 * Returns the type definition or NULL in case of error
7386 */
7387static xmlSchemaTypePtr
7388xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007389 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007390{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007391 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007392 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007393 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00007394 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007395 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00007396
7397 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7398 return (NULL);
7399
Daniel Veillard01fa6152004-06-29 17:04:39 +00007400 ctxtType = ctxt->ctxtType;
7401
Daniel Veillard4255d502002-04-16 15:50:10 +00007402 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007403 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007404 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007405 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007406 name = (const xmlChar *)buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00007407 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007408 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007409
William M. Bracke7091952004-05-11 15:09:58 +00007410 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
William M. Brack2f2a6632004-08-20 23:09:47 +00007411 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007412 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007413 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00007414 return (NULL);
7415 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007416 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00007417 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00007418
Daniel Veillard4255d502002-04-16 15:50:10 +00007419 type->node = node;
7420 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00007421 if (topLevel)
7422 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007423 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007424 ctxt->container = name;
7425
7426 child = node->children;
7427 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007428 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7429 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007430 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007431 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007432 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00007433 /* 3.4.3 : 2.2
7434 * Specifying mixed='true' when the <simpleContent>
7435 * alternative is chosen has no effect
7436 */
7437 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7438 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007439 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7440 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007441 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007442 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7443 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007444 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007445 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007446
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007447 if (IS_SCHEMA(child, "all")) {
7448 subtype = xmlSchemaParseAll(ctxt, schema, child);
7449 child = child->next;
7450 } else if (IS_SCHEMA(child, "choice")) {
7451 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7452 child = child->next;
7453 } else if (IS_SCHEMA(child, "sequence")) {
7454 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7455 child = child->next;
7456 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007457 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007458 child = child->next;
7459 }
7460 if (subtype != NULL)
7461 type->subtypes = subtype;
7462 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007463 }
7464 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007465 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007466 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
7467 "Complex type definition \"%s\" has unexpected content.\n",
7468 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007469 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007470 if (type->attributeWildcard != NULL)
7471 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00007472 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007473 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007474 return (type);
7475}
7476
Daniel Veillard4255d502002-04-16 15:50:10 +00007477/**
7478 * xmlSchemaParseSchema:
7479 * @ctxt: a schema validation context
7480 * @node: a subtree containing XML Schema informations
7481 *
7482 * parse a XML schema definition from a node set
7483 * *WARNING* this interface is highly subject to change
7484 *
7485 * Returns the internal XML Schema structure built from the resource or
7486 * NULL in case of error
7487 */
7488static xmlSchemaPtr
7489xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7490{
7491 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007492 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007493 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007494 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007495
7496 if ((ctxt == NULL) || (node == NULL))
7497 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007498
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007499 nberrors = ctxt->nberrors;
7500 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007501 if (IS_SCHEMA(node, "schema")) {
7502 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007503 if (schema == NULL)
7504 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007505 attr = xmlSchemaGetPropNode(node, "targetNamespace");
7506 if (attr != NULL) {
7507 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7508 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
7509 /*
7510 * TODO: Should we proceed with an invalid target namespace?
7511 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007512 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
7513 } else {
7514 schema->targetNamespace = NULL;
7515 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007516 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007517 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007518 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7519 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7520
William M. Brack2f2a6632004-08-20 23:09:47 +00007521 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007522 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
7523 } else {
7524 xmlDocPtr doc;
7525
7526 doc = node->doc;
7527
7528 if ((doc != NULL) && (doc->URL != NULL)) {
7529 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7530 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007531 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007532 } else {
7533 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7534 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007536 }
7537 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007538 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007539 if (ctxt->nberrors != 0) {
7540 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007541 xmlSchemaFree(schema);
7542 schema = NULL;
7543 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007544 }
7545 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00007546#ifdef DEBUG
7547 if (schema == NULL)
7548 xmlGenericError(xmlGenericErrorContext,
7549 "xmlSchemaParse() failed\n");
7550#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007551 return (schema);
7552}
7553
7554/************************************************************************
7555 * *
7556 * Validating using Schemas *
7557 * *
7558 ************************************************************************/
7559
7560/************************************************************************
7561 * *
7562 * Reading/Writing Schemas *
7563 * *
7564 ************************************************************************/
7565
7566/**
7567 * xmlSchemaNewParserCtxt:
7568 * @URL: the location of the schema
7569 *
7570 * Create an XML Schemas parse context for that file/resource expected
7571 * to contain an XML Schemas file.
7572 *
7573 * Returns the parser context or NULL in case of error
7574 */
7575xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007576xmlSchemaNewParserCtxt(const char *URL)
7577{
Daniel Veillard4255d502002-04-16 15:50:10 +00007578 xmlSchemaParserCtxtPtr ret;
7579
7580 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007581 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007582
7583 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7584 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007585 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007586 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007587 return (NULL);
7588 }
7589 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007590 ret->dict = xmlDictCreate();
7591 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007592 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007593 return (ret);
7594}
7595
7596/**
Daniel Veillard6045c902002-10-09 21:13:59 +00007597 * xmlSchemaNewMemParserCtxt:
7598 * @buffer: a pointer to a char array containing the schemas
7599 * @size: the size of the array
7600 *
7601 * Create an XML Schemas parse context for that memory buffer expected
7602 * to contain an XML Schemas file.
7603 *
7604 * Returns the parser context or NULL in case of error
7605 */
7606xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007607xmlSchemaNewMemParserCtxt(const char *buffer, int size)
7608{
Daniel Veillard6045c902002-10-09 21:13:59 +00007609 xmlSchemaParserCtxtPtr ret;
7610
7611 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007612 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007613
7614 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7615 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007617 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007618 return (NULL);
7619 }
7620 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7621 ret->buffer = buffer;
7622 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007623 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00007624 return (ret);
7625}
7626
7627/**
Daniel Veillard9d751502003-10-29 13:21:47 +00007628 * xmlSchemaNewDocParserCtxt:
7629 * @doc: a preparsed document tree
7630 *
7631 * Create an XML Schemas parse context for that document.
7632 * NB. The document may be modified during the parsing process.
7633 *
7634 * Returns the parser context or NULL in case of error
7635 */
7636xmlSchemaParserCtxtPtr
7637xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
7638{
7639 xmlSchemaParserCtxtPtr ret;
7640
7641 if (doc == NULL)
7642 return (NULL);
7643
7644 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7645 if (ret == NULL) {
7646 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
7647 NULL);
7648 return (NULL);
7649 }
7650 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7651 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007652 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00007653 /* The application has responsibility for the document */
7654 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00007655
7656 return (ret);
7657}
7658
7659/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007660 * xmlSchemaFreeParserCtxt:
7661 * @ctxt: the schema parser context
7662 *
7663 * Free the resources associated to the schema parser context
7664 */
7665void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007666xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
7667{
Daniel Veillard4255d502002-04-16 15:50:10 +00007668 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007669 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007670 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007671 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007672 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00007673 xmlFree(ctxt);
7674}
7675
7676/************************************************************************
7677 * *
7678 * Building the content models *
7679 * *
7680 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007681
Daniel Veillard4255d502002-04-16 15:50:10 +00007682/**
7683 * xmlSchemaBuildAContentModel:
7684 * @type: the schema type definition
7685 * @ctxt: the schema parser context
7686 * @name: the element name whose content is being built
7687 *
7688 * Generate the automata sequence needed for that type
7689 */
7690static void
7691xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007692 xmlSchemaParserCtxtPtr ctxt,
7693 const xmlChar * name)
7694{
Daniel Veillard4255d502002-04-16 15:50:10 +00007695 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007696 xmlGenericError(xmlGenericErrorContext,
7697 "Found unexpected type = NULL in %s content model\n",
7698 name);
7699 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007700 }
7701 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007702 case XML_SCHEMA_TYPE_ANY: {
7703 xmlAutomataStatePtr start, end;
7704 xmlSchemaWildcardPtr wild;
7705 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00007706
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 wild = type->attributeWildcard;
7708
7709 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007710 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 "Internal error: xmlSchemaBuildAContentModel, "
7712 "no wildcard on xsd:any.\n", NULL, NULL);
7713 return;
7714 }
7715
7716 start = ctxt->state;
7717 end = xmlAutomataNewState(ctxt->am);
7718
7719 if (type->maxOccurs == 1) {
7720 if (wild->any == 1) {
7721 /*
7722 * We need to add both transitions:
7723 *
7724 * 1. the {"*", "*"} for elements in a namespace.
7725 */
7726 ctxt->state =
7727 xmlAutomataNewTransition2(ctxt->am,
7728 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7729 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7730 /*
7731 * 2. the {"*"} for elements in no namespace.
7732 */
7733 ctxt->state =
7734 xmlAutomataNewTransition2(ctxt->am,
7735 start, NULL, BAD_CAST "*", NULL, type);
7736 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7737
7738 } else if (wild->nsSet != NULL) {
7739 ns = wild->nsSet;
7740 do {
7741 ctxt->state = start;
7742 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7743 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
7744 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7745 ns = ns->next;
7746 } while (ns != NULL);
7747
7748 } else if (wild->negNsSet != NULL) {
7749 xmlAutomataStatePtr deadEnd;
7750
7751 deadEnd = xmlAutomataNewState(ctxt->am);
7752 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7753 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7754 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7755 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7756 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7757 }
7758 } else {
7759 int counter;
7760 xmlAutomataStatePtr hop;
7761 int maxOccurs =
7762 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
7763 int minOccurs =
7764 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
7765
7766 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
7767 hop = xmlAutomataNewState(ctxt->am);
7768 if (wild->any == 1) {
7769 ctxt->state =
7770 xmlAutomataNewTransition2(ctxt->am,
7771 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7772 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7773 ctxt->state =
7774 xmlAutomataNewTransition2(ctxt->am,
7775 start, NULL, BAD_CAST "*", NULL, type);
7776 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7777 } else if (wild->nsSet != NULL) {
7778 ns = wild->nsSet;
7779 do {
7780 ctxt->state =
7781 xmlAutomataNewTransition2(ctxt->am,
7782 start, NULL, BAD_CAST "*", ns->value, type);
7783 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7784 ns = ns->next;
7785 } while (ns != NULL);
7786
7787 } else if (wild->negNsSet != NULL) {
7788 xmlAutomataStatePtr deadEnd;
7789
7790 deadEnd = xmlAutomataNewState(ctxt->am);
7791 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7792 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7793 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7794 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7795 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7796 }
7797 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
7798 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
7799 }
7800 if (type->minOccurs == 0) {
7801 xmlAutomataNewEpsilon(ctxt->am, start, end);
7802 }
7803 ctxt->state = end;
7804 break;
7805 }
7806 case XML_SCHEMA_TYPE_ELEMENT:{
7807 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
7808
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007809 /* TODO : handle the namespace too */
7810 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007811
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007812 if (elem->maxOccurs >= UNBOUNDED) {
7813 if (elem->minOccurs > 1) {
7814 xmlAutomataStatePtr tmp;
7815 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007817 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7818 oldstate,
7819 NULL);
7820 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007821
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007822 counter = xmlAutomataNewCounter(ctxt->am,
7823 elem->minOccurs -
7824 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00007825
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007826 if (elem->refDecl != NULL) {
7827 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7828 elem->refDecl,
7829 ctxt,
7830 elem->refDecl->
7831 name);
7832 } else {
7833 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007834 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007835 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007836 elem->name,
7837 elem->targetNamespace,
7838 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007839 }
7840 tmp = ctxt->state;
7841 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7842 counter);
7843 ctxt->state =
7844 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7845 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00007846
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007847 } else {
7848 if (elem->refDecl != NULL) {
7849 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7850 elem->refDecl,
7851 ctxt,
7852 elem->refDecl->
7853 name);
7854 } else {
7855 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007856 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007857 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007858 elem->name,
7859 elem->targetNamespace,
7860 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007861 }
7862 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7863 oldstate);
7864 if (elem->minOccurs == 0) {
7865 /* basically an elem* */
7866 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7867 ctxt->state);
7868 }
7869 }
7870 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
7871 xmlAutomataStatePtr tmp;
7872 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007873
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007874 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7875 oldstate, NULL);
7876 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007877
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007878 counter = xmlAutomataNewCounter(ctxt->am,
7879 elem->minOccurs - 1,
7880 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007881
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007882 if (elem->refDecl != NULL) {
7883 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7884 elem->refDecl, ctxt,
7885 elem->refDecl->name);
7886 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007887 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007888 ctxt->state,
7889 NULL,
7890 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007891 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007892 type);
7893 }
7894 tmp = ctxt->state;
7895 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7896 counter);
7897 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
7898 NULL,
7899 counter);
7900 if (elem->minOccurs == 0) {
7901 /* basically an elem? */
7902 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7903 ctxt->state);
7904 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00007905
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007906 } else {
7907 if (elem->refDecl != NULL) {
7908 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7909 elem->refDecl, ctxt,
7910 elem->refDecl->name);
7911 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007912 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007913 ctxt->state,
7914 NULL,
7915 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007916 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 type);
7918 }
7919 if (elem->minOccurs == 0) {
7920 /* basically an elem? */
7921 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7922 ctxt->state);
7923 }
7924 }
7925 break;
7926 }
7927 case XML_SCHEMA_TYPE_SEQUENCE:{
7928 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007929
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007930 /*
7931 * If max and min occurances are default (1) then
7932 * simply iterate over the subtypes
7933 */
7934 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
7935 subtypes = type->subtypes;
7936 while (subtypes != NULL) {
7937 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7938 subtypes = subtypes->next;
7939 }
7940 } else {
7941 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007942
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007943 if (type->maxOccurs >= UNBOUNDED) {
7944 if (type->minOccurs > 1) {
7945 xmlAutomataStatePtr tmp;
7946 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007947
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007948 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7949 oldstate,
7950 NULL);
7951 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007952
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007953 counter = xmlAutomataNewCounter(ctxt->am,
7954 type->
7955 minOccurs - 1,
7956 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007957
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007958 subtypes = type->subtypes;
7959 while (subtypes != NULL) {
7960 xmlSchemaBuildAContentModel(subtypes, ctxt,
7961 name);
7962 subtypes = subtypes->next;
7963 }
7964 tmp = ctxt->state;
7965 xmlAutomataNewCountedTrans(ctxt->am, tmp,
7966 oldstate, counter);
7967 ctxt->state =
7968 xmlAutomataNewCounterTrans(ctxt->am, tmp,
7969 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007970
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007971 } else {
7972 subtypes = type->subtypes;
7973 while (subtypes != NULL) {
7974 xmlSchemaBuildAContentModel(subtypes, ctxt,
7975 name);
7976 subtypes = subtypes->next;
7977 }
7978 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7979 oldstate);
7980 if (type->minOccurs == 0) {
7981 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7982 ctxt->state);
7983 }
7984 }
7985 } else if ((type->maxOccurs > 1)
7986 || (type->minOccurs > 1)) {
7987 xmlAutomataStatePtr tmp;
7988 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007989
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007990 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7991 oldstate,
7992 NULL);
7993 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00007994
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007995 counter = xmlAutomataNewCounter(ctxt->am,
7996 type->minOccurs -
7997 1,
7998 type->maxOccurs -
7999 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008000
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008001 subtypes = type->subtypes;
8002 while (subtypes != NULL) {
8003 xmlSchemaBuildAContentModel(subtypes, ctxt,
8004 name);
8005 subtypes = subtypes->next;
8006 }
8007 tmp = ctxt->state;
8008 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8009 counter);
8010 ctxt->state =
8011 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8012 counter);
8013 if (type->minOccurs == 0) {
8014 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8015 ctxt->state);
8016 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008017
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008018 } else {
8019 subtypes = type->subtypes;
8020 while (subtypes != NULL) {
8021 xmlSchemaBuildAContentModel(subtypes, ctxt,
8022 name);
8023 subtypes = subtypes->next;
8024 }
8025 if (type->minOccurs == 0) {
8026 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8027 ctxt->state);
8028 }
8029 }
8030 }
8031 break;
8032 }
8033 case XML_SCHEMA_TYPE_CHOICE:{
8034 xmlSchemaTypePtr subtypes;
8035 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008036
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008037 start = ctxt->state;
8038 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008039
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040 /*
8041 * iterate over the subtypes and remerge the end with an
8042 * epsilon transition
8043 */
8044 if (type->maxOccurs == 1) {
8045 subtypes = type->subtypes;
8046 while (subtypes != NULL) {
8047 ctxt->state = start;
8048 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8049 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8050 subtypes = subtypes->next;
8051 }
8052 } else {
8053 int counter;
8054 xmlAutomataStatePtr hop;
8055 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8056 UNBOUNDED : type->maxOccurs - 1;
8057 int minOccurs =
8058 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008059
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008060 /*
8061 * use a counter to keep track of the number of transtions
8062 * which went through the choice.
8063 */
8064 counter =
8065 xmlAutomataNewCounter(ctxt->am, minOccurs,
8066 maxOccurs);
8067 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008068
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008069 subtypes = type->subtypes;
8070 while (subtypes != NULL) {
8071 ctxt->state = start;
8072 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8073 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8074 subtypes = subtypes->next;
8075 }
8076 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8077 counter);
8078 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8079 counter);
8080 }
8081 if (type->minOccurs == 0) {
8082 xmlAutomataNewEpsilon(ctxt->am, start, end);
8083 }
8084 ctxt->state = end;
8085 break;
8086 }
8087 case XML_SCHEMA_TYPE_ALL:{
8088 xmlAutomataStatePtr start;
8089 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008090
Daniel Veillard3646d642004-06-02 19:19:14 +00008091 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008092 int lax;
8093
8094 subtypes = type->subtypes;
8095 if (subtypes == NULL)
8096 break;
8097 start = ctxt->state;
8098 while (subtypes != NULL) {
8099 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008100 /*
8101 * the following 'if' was needed to fix bug 139897
8102 * not quite sure why it only needs to be done for
8103 * elements with a 'ref', but it seems to work ok.
8104 */
8105 if (subtypes->ref != NULL)
8106 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00008107 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008108 /* TODO : handle the namespace too */
8109 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
8110 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
8111 ctxt->state, elem->name, 1,
8112 1, subtypes);
8113 } else {
8114 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
8115 ctxt->state, elem->name,
8116 elem->minOccurs,
8117 elem->maxOccurs,
8118 subtypes);
8119 }
8120 subtypes = subtypes->next;
8121 }
8122 lax = type->minOccurs == 0;
8123 ctxt->state =
8124 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8125 lax);
8126 break;
8127 }
8128 case XML_SCHEMA_TYPE_RESTRICTION:
8129 if (type->subtypes != NULL)
8130 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8131 break;
8132 case XML_SCHEMA_TYPE_EXTENSION:
8133 if (type->baseType != NULL) {
8134 xmlSchemaTypePtr subtypes;
8135
Daniel Veillardf7627552004-04-22 07:15:40 +00008136 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 /* TODO: Change the error code. */
8138 xmlSchemaPCustomErr(ctxt,
8139 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8140 NULL, type, type->node,
8141 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008142 return;
8143 }
8144 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008145 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008146 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008147 subtypes = type->subtypes;
8148 while (subtypes != NULL) {
8149 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8150 subtypes = subtypes->next;
8151 }
8152 } else if (type->subtypes != NULL)
8153 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8154 break;
8155 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008156 /*
8157 * Handle model group definition references.
8158 * NOTE: type->subtypes is the referenced model grop definition;
8159 * and type->subtypes->subtypes is the model group (i.e. <all> or
8160 * <choice> or <sequence>).
8161 */
8162 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8163 (type->subtypes->subtypes != NULL)) {
8164 xmlSchemaTypePtr modelGr;
8165 xmlAutomataStatePtr start, end;
8166
8167 modelGr = type->subtypes->subtypes;
8168 start = ctxt->state;
8169 end = xmlAutomataNewState(ctxt->am);
8170 if (type->maxOccurs == 1) {
8171 ctxt->state = start;
8172 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8173 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8174 } else {
8175 int counter;
8176 xmlAutomataStatePtr hop;
8177 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8178 UNBOUNDED : type->maxOccurs - 1;
8179 int minOccurs =
8180 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8181
8182 counter =
8183 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8184 hop = xmlAutomataNewState(ctxt->am);
8185 ctxt->state = start;
8186 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8187 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8188 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8189 counter);
8190 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8191 counter);
8192 }
8193 if (type->minOccurs == 0) {
8194 xmlAutomataNewEpsilon(ctxt->am, start, end);
8195 }
8196 ctxt->state = end;
8197 break;
8198 }
8199 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008200 case XML_SCHEMA_TYPE_COMPLEX:
8201 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8202 if (type->subtypes != NULL)
8203 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8204 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008205 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8206 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008207 default:
8208 xmlGenericError(xmlGenericErrorContext,
8209 "Found unexpected type %d in %s content model\n",
8210 type->type, name);
8211 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008212 }
8213}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008214
Daniel Veillard4255d502002-04-16 15:50:10 +00008215/**
8216 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008217 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008219 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008220 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008221 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00008222 */
8223static void
8224xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008225 xmlSchemaParserCtxtPtr ctxt,
8226 const xmlChar * name)
8227{
Daniel Veillard4255d502002-04-16 15:50:10 +00008228 xmlAutomataStatePtr start;
8229
Daniel Veillard4255d502002-04-16 15:50:10 +00008230 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008231 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008232 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008233 elem->contentType = XML_SCHEMA_CONTENT_ANY;
8234 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008235 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008236 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008237 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008238 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8239 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008240 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008241
8242#ifdef DEBUG_CONTENT
8243 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008244 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008245#endif
8246
Daniel Veillard4255d502002-04-16 15:50:10 +00008247 ctxt->am = xmlNewAutomata();
8248 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008249 xmlGenericError(xmlGenericErrorContext,
8250 "Cannot create automata for elem %s\n", name);
8251 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008252 }
8253 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
8254 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
8255 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00008256 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008257 if (elem->contModel == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008258 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008259 NULL, (xmlSchemaTypePtr) elem, NULL,
8260 "Failed to compile the content model", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008261 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008262 xmlSchemaPCustomErr(ctxt,
8263 XML_SCHEMAP_NOT_DETERMINISTIC,
8264 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008265 NULL, (xmlSchemaTypePtr) elem, NULL,
8266 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008267 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008268#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008269 xmlGenericError(xmlGenericErrorContext,
8270 "Content model of %s:\n", name);
8271 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008272#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008273 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008274 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008275 xmlFreeAutomata(ctxt->am);
8276 ctxt->am = NULL;
8277}
8278
8279/**
8280 * xmlSchemaRefFixupCallback:
8281 * @elem: the schema element context
8282 * @ctxt: the schema parser context
8283 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008284 * Resolves the references of an element declaration
8285 * or particle, which has an element declaration as it's
8286 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008287 */
8288static void
8289xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008290 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008291 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008292 const xmlChar * context ATTRIBUTE_UNUSED,
8293 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008294{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008295 if ((ctxt == NULL) || (elem == NULL) ||
8296 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008297 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008298 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008299 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008300 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008301
Daniel Veillardc0826a72004-08-10 14:17:33 +00008302 /*
8303 * TODO: Evaluate, what errors could occur if the declaration is not
8304 * found. It might be possible that the "typefixup" might crash if
8305 * no ref declaration was found.
8306 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008307 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008308 if (elemDecl == NULL) {
8309 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008310 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008311 NULL, (xmlSchemaTypePtr) elem, elem->node,
8312 "ref", elem->ref, elem->refNs,
8313 XML_SCHEMA_TYPE_ELEMENT, NULL);
8314 } else
8315 elem->refDecl = elemDecl;
8316 } else {
8317 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8318 xmlSchemaTypePtr type;
8319
8320 /* (type definition) ... otherwise the type definition ·resolved·
8321 * to by the ·actual value· of the type [attribute] ...
8322 */
8323 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8324 elem->namedTypeNs);
8325 if (type == NULL) {
8326 xmlSchemaPResCompAttrErr(ctxt,
8327 XML_SCHEMAP_SRC_RESOLVE,
8328 NULL, (xmlSchemaTypePtr) elem, elem->node,
8329 "type", elem->namedType, elem->namedTypeNs,
8330 XML_SCHEMA_TYPE_BASIC, "type definition");
8331 } else
8332 elem->subtypes = type;
8333 }
8334 if (elem->substGroup != NULL) {
8335 xmlSchemaElementPtr substHead;
8336
8337 /*
8338 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8339 * substitutionGroup?
8340 */
8341 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008342 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008343 if (substHead == NULL) {
8344 xmlSchemaPResCompAttrErr(ctxt,
8345 XML_SCHEMAP_SRC_RESOLVE,
8346 NULL, (xmlSchemaTypePtr) elem, NULL,
8347 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8348 XML_SCHEMA_TYPE_ELEMENT, NULL);
8349 } else {
8350 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8351 /*
8352 * (type definition)...otherwise the {type definition} of the
8353 * element declaration ·resolved· to by the ·actual value· of
8354 * the substitutionGroup [attribute], if present
8355 */
8356 if (elem->subtypes == NULL)
8357 elem->subtypes = substHead->subtypes;
8358 }
8359 }
8360 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8361 (elem->substGroup == NULL))
8362 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8363 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008364}
8365
William M. Bracke7091952004-05-11 15:09:58 +00008366/**
8367 * xmlSchemaParseListRefFixup:
8368 * @type: the schema type definition
8369 * @ctxt: the schema parser context
8370 *
8371 * Fixup of the itemType reference of the list type.
8372 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008373static void
William M. Bracke7091952004-05-11 15:09:58 +00008374xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008375{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008376
Daniel Veillard01fa6152004-06-29 17:04:39 +00008377 if (((type->base == NULL) &&
8378 (type->subtypes == NULL)) ||
8379 ((type->base != NULL) &&
8380 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008381 /*
8382 * src-list-itemType-or-simpleType
8383 * Either the itemType [attribute] or the <simpleType> [child] of
8384 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008385 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008386 /*
8387 * TODO: Move this to the parse function.
8388 */
8389 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008390 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008391 NULL, type, type->node,
8392 "The attribute 'itemType' and the <simpleType> child "
8393 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008394 } else if (type->base!= NULL) {
8395 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
8396 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008397 xmlSchemaPResCompAttrErr(ctxt,
8398 XML_SCHEMAP_SRC_RESOLVE,
8399 NULL, type, type->node,
8400 "itemType", type->base, type->baseNs,
8401 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008402 }
8403 }
8404 if ((type->subtypes != NULL) &&
8405 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8406 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008407}
8408
8409/**
8410 * xmlSchemaParseUnionRefCheck:
8411 * @typeDecl: the schema type definition
8412 * @ctxt: the schema parser context
8413 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00008414 * Checks and builds the memberTypes of the union type.
8415 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00008416 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008417static int
William M. Bracke7091952004-05-11 15:09:58 +00008418xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00008419 xmlSchemaParserCtxtPtr ctxt)
8420{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008421
Daniel Veillard01fa6152004-06-29 17:04:39 +00008422 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
8423 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00008424
Daniel Veillard01fa6152004-06-29 17:04:39 +00008425 /* 1 If the <union> alternative is chosen, then [Definition:]
8426 * define the explicit members as the type definitions ·resolved·
8427 * to by the items in the ·actual value· of the memberTypes [attribute],
8428 * if any, followed by the type definitions corresponding to the
8429 * <simpleType>s among the [children] of <union>, if any.
8430 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008431
Daniel Veillard01fa6152004-06-29 17:04:39 +00008432 if (type->type != XML_SCHEMA_TYPE_UNION)
8433 return (-1);
8434 if (ctxt->ctxtType == NULL) {
8435 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008436 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008437 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
8438 "available", NULL, NULL);
8439 return (-1);
8440 }
8441 /*
8442 * src-union-memberTypes-or-simpleTypes
8443 * Either the memberTypes [attribute] of the <union> element must
8444 * be non-empty or there must be at least one simpleType [child].
8445 */
8446 if ((type->base == NULL) &&
8447 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008448 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008449 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008450 NULL, NULL, type->node,
8451 "Either the attribute 'memberTypes' must be non-empty "
8452 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008453 }
8454
8455 ctxtType = ctxt->ctxtType;
8456 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008457 xmlAttrPtr attr;
8458 const xmlChar *cur, *end;
8459 xmlChar *tmp;
8460 const xmlChar *localName, *uri;
8461
8462 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00008463 cur = type->base;
8464 do {
8465 while (IS_BLANK_CH(*cur))
8466 cur++;
8467 end = cur;
8468 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8469 end++;
8470 if (end == cur)
8471 break;
8472 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008473 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
8474 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
8475 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008476 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008477 xmlSchemaPResCompAttrErr(ctxt,
8478 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
8479 NULL, NULL, type->node, "memberTypes", localName, uri,
8480 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008481 } else {
8482 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8483 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8484 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8485 if (link == NULL) {
8486 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8487 return (-1);
8488 }
8489 link->type = memberType;
8490 link->next = NULL;
8491 if (lastLink == NULL)
8492 ctxtType->memberTypes = link;
8493 else
8494 lastLink->next = link;
8495 lastLink = link;
8496 }
8497 xmlFree(tmp);
8498 cur = end;
8499 } while (*cur != 0);
8500 }
8501 /*
8502 * Add local simple types,
8503 */
8504 memberType = type->subtypes;
8505 while (memberType != NULL) {
8506 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8507 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8508 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8509 if (link == NULL) {
8510 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8511 return (-1);
8512 }
8513 link->type = memberType;
8514 link->next = NULL;
8515 if (lastLink == NULL)
8516 ctxtType->memberTypes = link;
8517 else
8518 lastLink->next = link;
8519 lastLink = link;
8520 memberType = memberType->next;
8521 }
8522 /*
8523 * The actual value is then formed by replacing any union type
8524 * definition in the ·explicit members· with the members of their
8525 * {member type definitions}, in order.
8526 */
8527 link = ctxtType->memberTypes;
8528 while (link != NULL) {
8529 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
8530 subLink = link->type->memberTypes;
8531 if (subLink != NULL) {
8532 link->type = subLink->type;
8533 if (subLink->next != NULL) {
8534 lastLink = link->next;
8535 subLink = subLink->next;
8536 prevLink = link;
8537 while (subLink != NULL) {
8538 newLink = (xmlSchemaTypeLinkPtr)
8539 xmlMalloc(sizeof(xmlSchemaTypeLink));
8540 if (newLink == NULL) {
8541 xmlSchemaPErrMemory(ctxt, "allocating a type link",
8542 NULL);
8543 return (-1);
8544 }
8545 newLink->type = memberType;
8546 prevLink->next = newLink;
8547 prevLink = newLink;
8548 newLink->next = lastLink;
8549
8550 subLink = subLink->next;
8551 }
8552 }
8553 }
8554 }
8555 link = link->next;
8556 }
8557
8558 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00008559}
8560
Daniel Veillard4255d502002-04-16 15:50:10 +00008561/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008562 * xmlSchemaIsDerivedFromBuiltInType:
8563 * @ctxt: the schema parser context
8564 * @type: the type definition
8565 * @valType: the value type
8566 *
8567 *
8568 * Returns 1 if the type has the given value type, or
8569 * is derived from such a type.
8570 */
William M. Brack803812b2004-06-03 02:11:24 +00008571static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008572xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
8573 xmlSchemaTypePtr type, int valType)
8574{
8575 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008576 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00008577 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008578 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00008579 return(1);
8580 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
8581 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
8582 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
8583 ((xmlSchemaAttributePtr) type)->subtypes, valType));
8584 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
8585 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
8586 if (type->baseType != NULL)
8587 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
8588 valType));
8589 } else if ((type->subtypes != NULL) &&
8590 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
8591 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
8592 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
8593 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
8594 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
8595 valType));
8596 }
8597
8598 return (0);
8599}
8600
8601/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00008602 * xmlSchemaIsDerivedFromBuiltInType:
8603 * @type: the simpleType definition
8604 *
8605 * Returns the primitive type of the given type or
8606 * NULL in case of error.
8607 */
8608static xmlSchemaTypePtr
8609xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
8610{
8611 while (type != NULL) {
8612 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
8613 return (type);
8614 type = type->baseType;
8615 }
8616
8617 return (NULL);
8618}
8619
8620
8621/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008622 * xmlSchemaBuildAttributeUsesOwned:
8623 * @ctxt: the schema parser context
8624 * @type: the complex type definition
8625 * @cur: the attribute declaration list
8626 * @lastUse: the top of the attribute use list
8627 *
8628 * Builds the attribute uses list on the given complex type.
8629 * This one is supposed to be called by
8630 * xmlSchemaBuildAttributeValidation only.
8631 */
8632static int
8633xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
8634 xmlSchemaAttributePtr cur,
8635 xmlSchemaAttributeLinkPtr *uses,
8636 xmlSchemaAttributeLinkPtr *lastUse)
8637{
8638 xmlSchemaAttributeLinkPtr tmp;
8639 while (cur != NULL) {
8640 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
8641 /*
8642 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
8643 * to by the ·actual value·s of the ref [attribute] of the
8644 * <attributeGroup> [children], if any."
8645 */
8646 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
8647 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
8648 lastUse) == -1) {
8649 return (-1);
8650 }
8651 } else {
8652 /* W3C: "1 The set of attribute uses corresponding to the
8653 * <attribute> [children], if any."
8654 */
8655 tmp = (xmlSchemaAttributeLinkPtr)
8656 xmlMalloc(sizeof(xmlSchemaAttributeLink));
8657 if (tmp == NULL) {
8658 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
8659 return (-1);
8660 }
8661 tmp->attr = cur;
8662 tmp->next = NULL;
8663 if (*uses == NULL)
8664 *uses = tmp;
8665 else
8666 (*lastUse)->next = tmp;
8667 *lastUse = tmp;
8668 }
8669 cur = cur->next;
8670 }
8671 return (0);
8672}
8673
Daniel Veillard50355f02004-06-08 17:52:16 +00008674/**
8675 * xmlSchemaCloneWildcardNsConstraints:
8676 * @ctxt: the schema parser context
8677 * @dest: the destination wildcard
8678 * @source: the source wildcard
8679 *
8680 * Clones the namespace constraints of source
8681 * and assignes them to dest.
8682 * Returns -1 on internal error, 0 otherwise.
8683 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008684static int
8685xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
8686 xmlSchemaWildcardPtr *dest,
8687 xmlSchemaWildcardPtr source)
8688{
8689 xmlSchemaWildcardNsPtr cur, tmp, last;
8690
8691 if ((source == NULL) || (*dest == NULL))
8692 return(-1);
8693 (*dest)->any = source->any;
8694 cur = source->nsSet;
8695 last = NULL;
8696 while (cur != NULL) {
8697 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8698 if (tmp == NULL)
8699 return(-1);
8700 tmp->value = cur->value;
8701 if (last == NULL)
8702 (*dest)->nsSet = tmp;
8703 else
8704 last->next = tmp;
8705 last = tmp;
8706 cur = cur->next;
8707 }
8708 if ((*dest)->negNsSet != NULL)
8709 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
8710 if (source->negNsSet != NULL) {
8711 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8712 if ((*dest)->negNsSet == NULL)
8713 return(-1);
8714 (*dest)->negNsSet->value = source->negNsSet->value;
8715 } else
8716 (*dest)->negNsSet = NULL;
8717 return(0);
8718}
8719
Daniel Veillard50355f02004-06-08 17:52:16 +00008720/**
8721 * xmlSchemaUnionWildcards:
8722 * @ctxt: the schema parser context
8723 * @completeWild: the first wildcard
8724 * @curWild: the second wildcard
8725 *
8726 * Unions the namespace constraints of the given wildcards.
8727 * @completeWild will hold the resulting union.
8728 * Returns a positive error code on failure, -1 in case of an
8729 * internal error, 0 otherwise.
8730 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008731static int
8732xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
8733 xmlSchemaWildcardPtr completeWild,
8734 xmlSchemaWildcardPtr curWild)
8735{
8736 xmlSchemaWildcardNsPtr cur, curB, tmp;
8737
8738 /*
8739 * 1 If O1 and O2 are the same value, then that value must be the
8740 * value.
8741 */
8742 if ((completeWild->any == curWild->any) &&
8743 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8744 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8745
8746 if ((completeWild->negNsSet == NULL) ||
8747 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8748
8749 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008750 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008751
8752 /*
8753 * Check equality of sets.
8754 */
8755 cur = completeWild->nsSet;
8756 while (cur != NULL) {
8757 found = 0;
8758 curB = curWild->nsSet;
8759 while (curB != NULL) {
8760 if (cur->value == curB->value) {
8761 found = 1;
8762 break;
8763 }
8764 curB = curB->next;
8765 }
8766 if (!found)
8767 break;
8768 cur = cur->next;
8769 }
8770 if (found)
8771 return(0);
8772 } else
8773 return(0);
8774 }
8775 }
8776 /*
8777 * 2 If either O1 or O2 is any, then any must be the value
8778 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008779 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008780 if (completeWild->any == 0) {
8781 completeWild->any = 1;
8782 if (completeWild->nsSet != NULL) {
8783 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8784 completeWild->nsSet = NULL;
8785 }
8786 if (completeWild->negNsSet != NULL) {
8787 xmlFree(completeWild->negNsSet);
8788 completeWild->negNsSet = NULL;
8789 }
8790 }
Daniel Veillard50355f02004-06-08 17:52:16 +00008791 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008792 }
8793 /*
8794 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
8795 * then the union of those sets must be the value.
8796 */
8797 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8798 int found;
8799 xmlSchemaWildcardNsPtr start;
8800
8801 cur = curWild->nsSet;
8802 start = completeWild->nsSet;
8803 while (cur != NULL) {
8804 found = 0;
8805 curB = start;
8806 while (curB != NULL) {
8807 if (cur->value == curB->value) {
8808 found = 1;
8809 break;
8810 }
8811 curB = curB->next;
8812 }
8813 if (!found) {
8814 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8815 if (tmp == NULL)
8816 return (-1);
8817 tmp->value = cur->value;
8818 tmp->next = completeWild->nsSet;
8819 completeWild->nsSet = tmp;
8820 }
8821 cur = cur->next;
8822 }
8823
8824 return(0);
8825 }
8826 /*
8827 * 4 If the two are negations of different values (namespace names
8828 * or ·absent·), then a pair of not and ·absent· must be the value.
8829 */
8830 if ((completeWild->negNsSet != NULL) &&
8831 (curWild->negNsSet != NULL) &&
8832 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
8833 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00008834
8835 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008836 }
8837 /*
8838 * 5.
8839 */
8840 if (((completeWild->negNsSet != NULL) &&
8841 (completeWild->negNsSet->value != NULL) &&
8842 (curWild->nsSet != NULL)) ||
8843 ((curWild->negNsSet != NULL) &&
8844 (curWild->negNsSet->value != NULL) &&
8845 (completeWild->nsSet != NULL))) {
8846
8847 int nsFound, absentFound = 0;
8848
8849 if (completeWild->nsSet != NULL) {
8850 cur = completeWild->nsSet;
8851 curB = curWild->negNsSet;
8852 } else {
8853 cur = curWild->nsSet;
8854 curB = completeWild->negNsSet;
8855 }
8856 nsFound = 0;
8857 while (cur != NULL) {
8858 if (cur->value == NULL)
8859 absentFound = 1;
8860 else if (cur->value == curB->value)
8861 nsFound = 1;
8862 if (nsFound && absentFound)
8863 break;
8864 cur = cur->next;
8865 }
8866
8867 if (nsFound && absentFound) {
8868 /*
8869 * 5.1 If the set S includes both the negated namespace
8870 * name and ·absent·, then any must be the value.
8871 */
8872 completeWild->any = 1;
8873 if (completeWild->nsSet != NULL) {
8874 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8875 completeWild->nsSet = NULL;
8876 }
8877 if (completeWild->negNsSet != NULL) {
8878 xmlFree(completeWild->negNsSet);
8879 completeWild->negNsSet = NULL;
8880 }
8881 } else if (nsFound && (!absentFound)) {
8882 /*
8883 * 5.2 If the set S includes the negated namespace name
8884 * but not ·absent·, then a pair of not and ·absent· must
8885 * be the value.
8886 */
8887 if (completeWild->nsSet != NULL) {
8888 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8889 completeWild->nsSet = NULL;
8890 }
8891 if (completeWild->negNsSet == NULL) {
8892 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8893 if (completeWild->negNsSet == NULL)
8894 return (-1);
8895 }
8896 completeWild->negNsSet->value = NULL;
8897 } else if ((!nsFound) && absentFound) {
8898 /*
8899 * 5.3 If the set S includes ·absent· but not the negated
8900 * namespace name, then the union is not expressible.
8901 */
8902 xmlSchemaPErr(ctxt, completeWild->node,
8903 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008904 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008905 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008906 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008907 } else if ((!nsFound) && (!absentFound)) {
8908 /*
8909 * 5.4 If the set S does not include either the negated namespace
8910 * name or ·absent·, then whichever of O1 or O2 is a pair of not
8911 * and a namespace name must be the value.
8912 */
8913 if (completeWild->negNsSet == NULL) {
8914 if (completeWild->nsSet != NULL) {
8915 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8916 completeWild->nsSet = NULL;
8917 }
8918 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8919 if (completeWild->negNsSet == NULL)
8920 return (-1);
8921 completeWild->negNsSet->value = curWild->negNsSet->value;
8922 }
8923 }
8924 return (0);
8925 }
8926 /*
8927 * 6.
8928 */
8929 if (((completeWild->negNsSet != NULL) &&
8930 (completeWild->negNsSet->value == NULL) &&
8931 (curWild->nsSet != NULL)) ||
8932 ((curWild->negNsSet != NULL) &&
8933 (curWild->negNsSet->value == NULL) &&
8934 (completeWild->nsSet != NULL))) {
8935
8936 if (completeWild->nsSet != NULL) {
8937 cur = completeWild->nsSet;
8938 } else {
8939 cur = curWild->nsSet;
8940 }
8941 while (cur != NULL) {
8942 if (cur->value == NULL) {
8943 /*
8944 * 6.1 If the set S includes ·absent·, then any must be the
8945 * value.
8946 */
8947 completeWild->any = 1;
8948 if (completeWild->nsSet != NULL) {
8949 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8950 completeWild->nsSet = NULL;
8951 }
8952 if (completeWild->negNsSet != NULL) {
8953 xmlFree(completeWild->negNsSet);
8954 completeWild->negNsSet = NULL;
8955 }
8956 return (0);
8957 }
8958 cur = cur->next;
8959 }
8960 if (completeWild->negNsSet == NULL) {
8961 /*
8962 * 6.2 If the set S does not include ·absent·, then a pair of not
8963 * and ·absent· must be the value.
8964 */
8965 if (completeWild->nsSet != NULL) {
8966 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8967 completeWild->nsSet = NULL;
8968 }
8969 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8970 if (completeWild->negNsSet == NULL)
8971 return (-1);
8972 completeWild->negNsSet->value = NULL;
8973 }
8974 return (0);
8975 }
8976 return (0);
8977
8978}
8979
Daniel Veillard50355f02004-06-08 17:52:16 +00008980/**
8981 * xmlSchemaIntersectWildcards:
8982 * @ctxt: the schema parser context
8983 * @completeWild: the first wildcard
8984 * @curWild: the second wildcard
8985 *
8986 * Intersects the namespace constraints of the given wildcards.
8987 * @completeWild will hold the resulting intersection.
8988 * Returns a positive error code on failure, -1 in case of an
8989 * internal error, 0 otherwise.
8990 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008991static int
8992xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
8993 xmlSchemaWildcardPtr completeWild,
8994 xmlSchemaWildcardPtr curWild)
8995{
William M. Brack803812b2004-06-03 02:11:24 +00008996 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008997
8998 /*
8999 * 1 If O1 and O2 are the same value, then that value must be the
9000 * value.
9001 */
9002 if ((completeWild->any == curWild->any) &&
9003 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9004 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9005
9006 if ((completeWild->negNsSet == NULL) ||
9007 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9008
9009 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009010 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009011
9012 /*
9013 * Check equality of sets.
9014 */
9015 cur = completeWild->nsSet;
9016 while (cur != NULL) {
9017 found = 0;
9018 curB = curWild->nsSet;
9019 while (curB != NULL) {
9020 if (cur->value == curB->value) {
9021 found = 1;
9022 break;
9023 }
9024 curB = curB->next;
9025 }
9026 if (!found)
9027 break;
9028 cur = cur->next;
9029 }
9030 if (found)
9031 return(0);
9032 } else
9033 return(0);
9034 }
9035 }
9036 /*
9037 * 2 If either O1 or O2 is any, then the other must be the value.
9038 */
9039 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9040 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9041 return(-1);
9042 return(0);
9043 }
9044 /*
9045 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9046 * name or ·absent·) and the other is a set of (namespace names or
9047 * ·absent·), then that set, minus the negated value if it was in
9048 * the set, minus ·absent· if it was in the set, must be the value.
9049 */
9050 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9051 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9052 const xmlChar *neg;
9053
9054 if (completeWild->nsSet == NULL) {
9055 neg = completeWild->negNsSet->value;
9056 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9057 return(-1);
9058 } else
9059 neg = curWild->negNsSet->value;
9060 /*
9061 * Remove absent and negated.
9062 */
9063 prev = NULL;
9064 cur = completeWild->nsSet;
9065 while (cur != NULL) {
9066 if (cur->value == NULL) {
9067 if (prev == NULL)
9068 completeWild->nsSet = cur->next;
9069 else
9070 prev->next = cur->next;
9071 xmlFree(cur);
9072 break;
9073 }
9074 prev = cur;
9075 cur = cur->next;
9076 }
9077 if (neg != NULL) {
9078 prev = NULL;
9079 cur = completeWild->nsSet;
9080 while (cur != NULL) {
9081 if (cur->value == neg) {
9082 if (prev == NULL)
9083 completeWild->nsSet = cur->next;
9084 else
9085 prev->next = cur->next;
9086 xmlFree(cur);
9087 break;
9088 }
9089 prev = cur;
9090 cur = cur->next;
9091 }
9092 }
9093
9094 return(0);
9095 }
9096 /*
9097 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9098 * then the intersection of those sets must be the value.
9099 */
9100 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9101 int found;
9102
9103 cur = completeWild->nsSet;
9104 prev = NULL;
9105 while (cur != NULL) {
9106 found = 0;
9107 curB = curWild->nsSet;
9108 while (curB != NULL) {
9109 if (cur->value == curB->value) {
9110 found = 1;
9111 break;
9112 }
9113 curB = curB->next;
9114 }
9115 if (!found) {
9116 if (prev == NULL)
9117 completeWild->nsSet = cur->next;
9118 else
9119 prev->next = cur->next;
9120 tmp = cur->next;
9121 xmlFree(cur);
9122 cur = tmp;
9123 continue;
9124 }
9125 prev = cur;
9126 cur = cur->next;
9127 }
9128
9129 return(0);
9130 }
9131 /* 5 If the two are negations of different namespace names,
9132 * then the intersection is not expressible
9133 */
9134 if ((completeWild->negNsSet != NULL) &&
9135 (curWild->negNsSet != NULL) &&
9136 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9137 (completeWild->negNsSet->value != NULL) &&
9138 (curWild->negNsSet->value != NULL)) {
9139
9140 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009141 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009142 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009143 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009144 }
9145 /*
9146 * 6 If the one is a negation of a namespace name and the other
9147 * is a negation of ·absent·, then the one which is the negation
9148 * of a namespace name must be the value.
9149 */
9150 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9151 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9152 (completeWild->negNsSet->value == NULL)) {
9153 completeWild->negNsSet->value = curWild->negNsSet->value;
9154 }
9155 return(0);
9156}
9157
Daniel Veillard50355f02004-06-08 17:52:16 +00009158/**
9159 * xmlSchemaIsWildcardNsConstraintSubset:
9160 * @ctxt: the schema parser context
9161 * @wildA: the first wildcard
9162 * @wildB: the second wildcard
9163 *
9164 * Returns 1 if the namespace constraint of @wildA is an intensional
9165 * subset of @wildB, 0 otherwise.
9166 */
9167static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009168xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9169 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009170{
Daniel Veillard3646d642004-06-02 19:19:14 +00009171
Daniel Veillard50355f02004-06-08 17:52:16 +00009172 /*
9173 * Schema Component Constraint: Wildcard Subset
9174 */
9175 /*
9176 * 1 super must be any.
9177 */
9178 if (wildB->any)
9179 return (1);
9180 /*
9181 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9182 * 2.2 super must be a pair of not and the same value.
9183 */
9184 if ((wildA->negNsSet != NULL) &&
9185 (wildB->negNsSet != NULL) &&
9186 (wildA->negNsSet->value == wildA->negNsSet->value))
9187 return (1);
9188 /*
9189 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9190 */
9191 if (wildA->nsSet != NULL) {
9192 /*
9193 * 3.2.1 super must be the same set or a superset thereof.
9194 */
9195 if (wildB->nsSet != NULL) {
9196 xmlSchemaWildcardNsPtr cur, curB;
9197 int found = 0;
9198
9199 cur = wildA->nsSet;
9200 while (cur != NULL) {
9201 found = 0;
9202 curB = wildB->nsSet;
9203 while (curB != NULL) {
9204 if (cur->value == curB->value) {
9205 found = 1;
9206 break;
9207 }
9208 curB = curB->next;
9209 }
9210 if (!found)
9211 return (0);
9212 cur = cur->next;
9213 }
9214 if (found)
9215 return (1);
9216 } else if (wildB->negNsSet != NULL) {
9217 xmlSchemaWildcardNsPtr cur;
9218 /*
9219 * 3.2.2 super must be a pair of not and a namespace name or
9220 * ·absent· and that value must not be in sub's set.
9221 */
9222 cur = wildA->nsSet;
9223 while (cur != NULL) {
9224 if (cur->value == wildB->negNsSet->value)
9225 return (0);
9226 cur = cur->next;
9227 }
9228 return (1);
9229 }
9230 }
9231 return (0);
9232}
9233
9234/**
9235 * xmlSchemaBuildCompleteAttributeWildcard:
9236 * @ctxt: the schema parser context
9237 * @attrs: the attribute list
9238 * @completeWild: the resulting complete wildcard
9239 *
9240 * Returns -1 in case of an internal error, 0 otherwise.
9241 */
9242static int
9243xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9244 xmlSchemaAttributePtr attrs,
9245 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009246{
9247 while (attrs != NULL) {
9248 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9249 xmlSchemaAttributeGroupPtr group;
9250
9251 group = (xmlSchemaAttributeGroupPtr) attrs;
9252 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9253 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009254 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9255 group->attributes, &group->attributeWildcard) == -1)
9256 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009257 }
9258 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9259 }
9260 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009261 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009262 /*
9263 * Copy the first encountered wildcard as context, except for the annotation.
9264 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009265 *completeWild = xmlSchemaAddWildcard(ctxt);
9266 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9267 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9268 completeWild, group->attributeWildcard) == -1)
9269 return (-1);
9270 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009271 /*
9272 * Although the complete wildcard might not correspond to any
9273 * node in the schema, we will save this context node.
9274 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009275 (*completeWild)->node = group->attributeWildcard->node;
9276
9277 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9278 xmlSchemaFreeWildcard(*completeWild);
9279 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009280 }
9281 }
9282 }
9283 attrs = attrs->next;
9284 }
9285
Daniel Veillard50355f02004-06-08 17:52:16 +00009286 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009287}
9288
9289/**
9290 * xmlSchemaMatchesWildcardNs:
9291 * @wild: the wildcard
9292 * @ns: the namespace
9293 *
9294 *
9295 * Returns 1 if the given namespace matches the wildcard,
9296 * 0 otherwise.
9297 */
9298static int
9299xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9300{
9301 if (wild == NULL)
9302 return(0);
9303
9304 if (wild->any)
9305 return(1);
9306 else if (wild->nsSet != NULL) {
9307 xmlSchemaWildcardNsPtr cur;
9308
9309 cur = wild->nsSet;
9310 while (cur != NULL) {
9311 if (xmlStrEqual(cur->value, ns))
9312 return(1);
9313 cur = cur->next;
9314 }
9315 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9316 (!xmlStrEqual(wild->negNsSet->value, ns)))
9317 return(1);
9318
9319 return(0);
9320}
9321
9322/**
9323 * xmlSchemaBuildAttributeValidation:
9324 * @ctxt: the schema parser context
9325 * @type: the complex type definition
9326 *
9327 *
9328 * Builds the wildcard and the attribute uses on the given complex type.
9329 * Returns -1 if an internal error occurs, 0 otherwise.
9330 */
9331static int
9332xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
9333{
9334 xmlSchemaTypePtr baseType = NULL;
9335 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00009336 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009337 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009338 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00009339 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009340 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009341 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009342
Daniel Veillard01fa6152004-06-29 17:04:39 +00009343 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009344 /*
9345 * Complex Type Definition with complex content Schema Component.
9346 *
9347 * Attribute uses.
9348 */
9349 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009350 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009351 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00009352 "attribute uses already builded.\n",
9353 NULL, NULL);
9354 return (-1);
9355 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009356 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009357 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009358 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009359 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009360 type->name, NULL);
9361 return (-1);
9362 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009363 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009364 if (baseType == anyType)
9365 baseIsAnyType = 1;
9366 /*
9367 * Inherit the attribute uses of the base type.
9368 */
9369 /*
9370 * NOTE: It is allowed to "extend" the anyType complex type.
9371 */
9372 if (!baseIsAnyType) {
9373 if (baseType != NULL) {
9374 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
9375 tmp = (xmlSchemaAttributeLinkPtr)
9376 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9377 if (tmp == NULL) {
9378 xmlSchemaPErrMemory(ctxt,
9379 "building attribute uses of complexType", NULL);
9380 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009381 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009382 tmp->attr = cur->attr;
9383 tmp->next = NULL;
9384 if (type->attributeUses == NULL) {
9385 type->attributeUses = tmp;
9386 } else
9387 lastBaseUse->next = tmp;
9388 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009389 }
9390 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009391 }
9392 if ((type->subtypes != NULL) &&
9393 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9394 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9395 attrs = type->subtypes->subtypes->attributes;
9396 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
9397 } else {
9398 /* Short hand form of the complexType. */
9399 attrs = type->attributes;
9400 }
9401 /*
9402 * Handle attribute wildcards.
9403 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009404 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9405 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009406 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009407 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
9408 * create the wildcard right from the start on the complexType,
9409 * rather than on the <restriction>/<extension>.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009410 *
9411 * This here simply checks if <complexType>-><restriction>|<extension>
9412 * does exist and its wildcard is used or not.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009413 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009414 if (type->attributeWildcard != NULL) {
9415 if ((type->subtypes == NULL) ||
9416 ((type->subtypes->type != XML_SCHEMA_TYPE_COMPLEX_CONTENT) &&
9417 (type->subtypes->type != XML_SCHEMA_TYPE_SIMPLE_CONTENT)) ||
9418 (type->subtypes->subtypes == NULL) ||
9419 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)) {
9420 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
9421 }
9422 }
9423 /*
9424 * Note that an error for the above call to
9425 * xmlSchemaBuildCompleteAttributeWildcard is processed here, since we
9426 * needed to set XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD beforehand.
9427 */
9428 if (err == -1)
9429 return (-1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009430
9431 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
9432 ((baseIsAnyType) ||
9433 ((baseType != NULL) &&
9434 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9435 (baseType->attributeWildcard != NULL)))) {
9436 if (type->attributeWildcard != NULL) {
9437 /*
9438 * Union the complete wildcard with the base wildcard.
9439 */
9440 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
9441 baseType->attributeWildcard) == -1)
9442 return (-1);
9443 } else {
9444 /*
9445 * Just inherit the wildcard.
9446 */
9447 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00009448 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009449 }
9450
9451 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9452 if (type->attributeWildcard != NULL) {
9453 /*
9454 * Derivation Valid (Restriction, Complex)
9455 * 4.1 The {base type definition} must also have one.
9456 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009457 if (baseType->attributeWildcard == NULL) {
9458 xmlSchemaPCustomErr(ctxt,
9459 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
9460 NULL, type, NULL,
9461 "The type has an attribute wildcard, "
9462 "but the base type %s does not have one",
9463 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9464 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009465 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009466 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009467 type->attributeWildcard, baseType->attributeWildcard) == 0) {
9468 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009469 xmlSchemaPCustomErr(ctxt,
9470 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
9471 NULL, type, NULL,
9472 "The attribute wildcard is not a valid "
9473 "subset of the wildcard in the base type %s",
9474 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9475 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009476 return (1);
9477 }
9478 /* 4.3 Unless the {base type definition} is the ·ur-type
9479 * definition·, the complex type definition's {attribute
9480 * wildcard}'s {process contents} must be identical to or
9481 * stronger than the {base type definition}'s {attribute
9482 * wildcard}'s {process contents}, where strict is stronger
9483 * than lax is stronger than skip.
9484 */
9485 if ((type->baseType != anyType) &&
9486 (type->attributeWildcard->processContents <
9487 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009488 xmlSchemaPCustomErr(ctxt,
9489 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
9490 NULL, type, NULL,
9491 "The 'process contents' of the attribute wildcard is weaker than "
9492 "the one in the base type %s",
9493 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9494 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009495 return (1);
9496 }
9497 }
9498 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9499 /*
9500 * Derivation Valid (Extension)
9501 * At this point the type and the base have both, either
9502 * no wildcard or a wildcard.
9503 */
9504 if ((baseType->attributeWildcard != NULL) &&
9505 (baseType->attributeWildcard != type->attributeWildcard)) {
9506 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009507 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009508 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 xmlSchemaPCustomErr(ctxt,
9510 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
9511 NULL, type, NULL,
9512 "The attribute wildcard is not a valid "
9513 "superset of the one in the base type %s",
9514 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9515 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009516 return (1);
9517 }
9518 }
9519 }
9520
Daniel Veillard3646d642004-06-02 19:19:14 +00009521 /*
9522 * Gather attribute uses defined by this type.
9523 */
9524 if (attrs != NULL) {
9525 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
9526 &uses, &lastUse) == -1) {
9527 return (-1);
9528 }
9529 }
9530 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
9531 * "Two distinct attribute declarations in the {attribute uses} must
9532 * not have identical {name}s and {target namespace}s."
9533 *
9534 * For "extension" this is done further down.
9535 */
9536 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
9537 cur = uses;
9538 while (cur != NULL) {
9539 tmp = cur->next;
9540 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009541 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9542 xmlSchemaGetAttrName(tmp->attr))) &&
9543 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9544 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
9545
9546 xmlSchemaPAttrUseErr(ctxt,
9547 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9548 NULL, type, NULL, cur->attr,
9549 "Duplicate attribute use %s specified",
9550 xmlSchemaFormatNsUriLocal(&str,
9551 xmlSchemaGetAttrTargetNsURI(tmp->attr),
9552 xmlSchemaGetAttrName(tmp->attr))
9553 );
9554 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009555 break;
9556 }
9557 tmp = tmp->next;
9558 }
9559 cur = cur->next;
9560 }
9561 }
9562 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9563 /*
9564 * Derive by restriction.
9565 */
9566 if (baseIsAnyType) {
9567 type->attributeUses = uses;
9568 } else {
9569 int found;
9570
9571 cur = uses;
9572 while (cur != NULL) {
9573 found = 0;
9574 base = type->attributeUses;
9575 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009576 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9577 xmlSchemaGetAttrName(base->attr)) &&
9578 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
9579 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009580
Daniel Veillardc0826a72004-08-10 14:17:33 +00009581 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009582 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
9583 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9584 /*
9585 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +00009586 */
9587 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00009588 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009589 NULL, type, NULL, cur->attr,
9590 "The 'optional' use is inconsistent with a matching "
9591 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009592 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
9593 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9594 /*
9595 * derivation-ok-restriction 3
9596 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009597 xmlSchemaPCustomErr(ctxt,
9598 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
9599 NULL, type, NULL,
9600 "A matching attribute use for the 'required' "
9601 "attribute use %s of the base type is missing",
9602 xmlSchemaFormatNsUriLocal(&str,
9603 xmlSchemaGetAttrTargetNsURI(base->attr),
9604 xmlSchemaGetAttrName(base->attr)));
9605 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009606 } else {
9607 /*
9608 * Override the attribute use.
9609 */
9610 base->attr = cur->attr;
9611 }
9612 /*
9613 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00009614 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00009615 */
9616 break;
9617 }
9618 base = base->next;
9619 }
9620
9621 if (!found) {
9622 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9623 /*
9624 * derivation-ok-restriction 2.2
9625 */
9626 if ((type->attributeWildcard != NULL) &&
9627 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
9628 cur->attr->targetNamespace))
9629 found = 1;
9630
9631 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009632 xmlSchemaPAttrUseErr(ctxt,
9633 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
9634 NULL, type, NULL, cur->attr,
9635 "Neither a matching attribute use, "
9636 "nor a matching wildcard in the base type does exist",
9637 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009638 } else {
9639 /*
9640 * Add the attribute use.
9641 *
9642 * Note that this may lead to funny derivation error reports, if
9643 * multiple equal attribute uses exist; but this is not
9644 * allowed anyway, and it will be reported beforehand.
9645 */
9646 tmp = cur;
9647 if (prev != NULL)
9648 prev->next = cur->next;
9649 else
9650 uses = cur->next;
9651 cur = cur->next;
9652 if (type->attributeUses == NULL) {
9653 type->attributeUses = tmp;
9654 } else
9655 lastBaseUse->next = tmp;
9656 lastBaseUse = tmp;
9657
9658 continue;
9659 }
9660 }
9661 }
9662 prev = cur;
9663 cur = cur->next;
9664 }
9665 if (uses != NULL)
9666 xmlSchemaFreeAttributeUseList(uses);
9667 }
9668 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9669 /*
9670 * The spec allows only appending, and not other kinds of extensions.
9671 *
9672 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
9673 */
9674 if (uses != NULL) {
9675 if (type->attributeUses == NULL) {
9676 type->attributeUses = uses;
9677 } else
9678 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009679 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009680 } else {
9681 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00009682 * Derive implicitely from the ur-type.
9683 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009684 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009685 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009686 /*
9687 * 3.4.6 -> Complex Type Definition Properties Correct
9688 */
9689 if (type->attributeUses != NULL) {
9690 cur = type->attributeUses;
9691 prev = NULL;
9692 while (cur != NULL) {
9693 /*
9694 * 4. Two distinct attribute declarations in the {attribute uses} must
9695 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00009696 *
Daniel Veillard3646d642004-06-02 19:19:14 +00009697 * Note that this was already done for "restriction" and types derived from
9698 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00009699 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009700 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9701 tmp = cur->next;
9702 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009703 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9704 xmlSchemaGetAttrName(tmp->attr))) &&
9705 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9706 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009707
Daniel Veillardc0826a72004-08-10 14:17:33 +00009708 xmlSchemaPAttrUseErr(ctxt,
9709 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9710 NULL, type, NULL, tmp->attr,
9711 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009712 break;
9713 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009714 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009715 }
9716 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009717 /*
9718 * 5. Two distinct attribute declarations in the {attribute uses} must
9719 * not have {type definition}s which are or are derived from ID.
9720 */
9721 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009722 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009723 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009724 xmlSchemaPAttrUseErr(ctxt,
9725 XML_SCHEMAP_CT_PROPS_CORRECT_5,
9726 NULL, type, NULL, cur->attr,
9727 "There must not exist more than one attribute use, "
9728 "declared of type 'ID' or derived from it",
9729 NULL);
9730 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +00009731 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009732 id = cur;
9733 }
9734 /*
9735 * Remove "prohibited" attribute uses. The reason this is done at this late
9736 * stage is to be able to catch dublicate attribute uses. So we had to keep
9737 * prohibited uses in the list as well.
9738 */
9739 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9740 tmp = cur;
9741 if (prev == NULL)
9742 type->attributeUses = cur->next;
9743 else
9744 prev->next = cur->next;
9745 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009746 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00009747 } else {
9748 prev = cur;
9749 cur = cur->next;
9750 }
9751 }
9752 }
9753 /*
9754 * TODO: This check should be removed if we are 100% sure of
9755 * the base type attribute uses already being built.
9756 */
9757 if ((baseType != NULL) && (!baseIsAnyType) &&
9758 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9759 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009760 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009761 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009762 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009763 baseType->name, NULL);
9764 }
9765 return (0);
9766}
9767
9768/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009769 * xmlSchemaTypeFinalContains:
9770 * @schema: the schema
9771 * @type: the type definition
9772 * @final: the final
9773 *
9774 * Evaluates if a type definition contains the given "final".
9775 * This does take "finalDefault" into account as well.
9776 *
9777 * Returns 1 if the type does containt the given "final",
9778 * 0 otherwise.
9779 */
9780static int
9781xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
9782{
9783 int tfinal = final, tflags = type->flags;
9784
9785 if (type == NULL)
9786 return (0);
9787 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
9788 switch (final) {
9789 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
9790 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9791 break;
9792 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
9793 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9794 break;
9795 case XML_SCHEMAS_TYPE_FINAL_LIST:
9796 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
9797 break;
9798 case XML_SCHEMAS_TYPE_FINAL_UNION:
9799 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
9800 break;
9801 }
9802 tflags = schema->flags;
9803 }
9804 if (tflags & tfinal)
9805 return (1);
9806 else
9807 return (0);
9808
9809}
9810
9811/**
9812 * xmlSchemaGetUnionSimpleTypeMemberTypes:
9813 * @type: the Union Simple Type
9814 *
9815 * Returns a list of member types of @type if existing,
9816 * returns NULL otherwise.
9817 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009818static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00009819xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
9820{
9821 while (type != NULL) {
9822 if (type->memberTypes != NULL)
9823 return (type->memberTypes);
9824 else
9825 type = type->baseType;
9826 }
9827 return (NULL);
9828}
9829
9830/**
9831 * xmlSchemaGetListSimpleTypeItemType:
9832 * @type: the simple type definition
9833 *
9834 * Returns the item type definition of the list simple type.
9835 */
9836static xmlSchemaTypePtr
9837xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
9838{
9839 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
9840 return (NULL);
9841 /*
9842 * Note: In libxml2, the built-in types do not reflect
9843 * the datatype hierarchy (yet?) - we have to treat them
9844 * in a special way.
9845 */
9846 if (type->type == XML_SCHEMA_TYPE_BASIC)
9847 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
9848 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
9849 /* 1 If the <list> alternative is chosen, then the type
9850 * definition ·resolved· to by the ·actual value· of the
9851 * itemType [attribute] of <list>, if present, otherwise
9852 * the type definition corresponding to the <simpleType>
9853 * among the [children] of <list>.
9854 */
9855 return (type->subtypes->subtypes);
9856 else {
9857 /* 2 If the <restriction> option is chosen, then the
9858 * {item type definition} of the {base type definition}.
9859 */
9860 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
9861 }
9862}
9863
9864/**
9865 * xmlSchemaCheckCOSSTDerivedOK:
9866 * @type: the derived simple type definition
9867 * @baseType: the base type definition
9868 *
9869 * Checks wheter @type can be validly
9870 * derived from @baseType.
9871 *
9872 * Returns 0 on success, an positive error code otherwise.
9873 */
9874static int
9875xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
9876 xmlSchemaTypePtr type,
9877 xmlSchemaTypePtr baseType,
9878 int subset)
9879{
9880 /*
9881 * Schema Component Constraint: Type Derivation OK (Simple)
9882 *
9883 *
9884 * 1 They are the same type definition.
9885 * TODO: The identy check might have to be more complex than this.
9886 */
9887 if (type == baseType)
9888 return (0);
9889 /*
9890 * 2.1 restriction is not in the subset, or in the {final}
9891 * of its own {base type definition};
9892 */
9893 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
9894 (xmlSchemaTypeFinalContains(schema,
9895 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
9896 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
9897 }
9898 /* 2.2 */
9899 if (type->baseType == baseType) {
9900 /*
9901 * 2.2.1 D's ·base type definition· is B.
9902 */
9903 return (0);
9904 }
9905 /*
9906 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
9907 * and is validly derived from B given the subset, as defined by this
9908 * constraint.
9909 */
9910 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
9911 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
9912 return (0);
9913 }
9914 /*
9915 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
9916 * definition·.
9917 */
9918 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
9919 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
9920 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
9921 return (0);
9922 }
9923 /*
9924 * 2.2.4 B's {variety} is union and D is validly derived from a type
9925 * definition in B's {member type definitions} given the subset, as
9926 * defined by this constraint.
9927 *
9928 * NOTE: This seems not to involve built-in types, since there is no
9929 * built-in Union Simple Type.
9930 */
9931 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9932 xmlSchemaTypeLinkPtr cur;
9933
9934 cur = baseType->memberTypes;
9935 while (cur != NULL) {
9936 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
9937 cur->type, subset) == 0)
9938 return (0);
9939 cur = cur->next;
9940 }
9941 }
9942
9943 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
9944}
9945
9946
9947/**
9948 * xmlSchemaCheckSTPropsCorrect:
9949 * @ctxt: the schema parser context
9950 * @type: the simple type definition
9951 *
9952 * Checks st-props-correct.
9953 *
9954 * Returns 0 if the properties are correct,
9955 * if not, a positive error code and -1 on internal
9956 * errors.
9957 */
9958static int
9959xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
9960 xmlSchemaTypePtr type)
9961{
9962 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
9963 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009964 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009965
Daniel Veillardc0826a72004-08-10 14:17:33 +00009966 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009967 /*
9968 * Schema Component Constraint: Simple Type Definition Properties Correct
9969 *
9970 * NOTE: This is somehow redundant, since we actually built a simple type
9971 * to have all the needed information; this acts as an self test.
9972 */
9973 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9974 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9975 /*
9976 * TODO: 1 The values of the properties of a simple type definition must be as
9977 * described in the property tableau in Datatype definition, modulo the
9978 * impact of Missing Sub-components (§5.3).
9979 */
9980 /* Base type: If the datatype has been ·derived· by ·restriction·
9981 * then the Simple Type Definition component from which it is ·derived·,
9982 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
9983 */
9984 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009985 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009986 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009987 NULL, type, NULL,
9988 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009989 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9990 }
9991 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
9992 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
9993 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009994 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009995 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009996 NULL, type, NULL,
9997 "The base type %s is not a simple type",
9998 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9999 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010000 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10001 }
10002 if ((baseType != anySimpleType) &&
10003 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010004 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010005 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010006 NULL, type, NULL,
10007 "A type, derived by list or union, must have"
10008 "the simple ur-type definition as base type, not %s",
10009 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10010 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010011 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10012 }
10013 /*
10014 * Variety: One of {atomic, list, union}.
10015 */
10016 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10017 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10018 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010019 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010020 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010021 NULL, type, NULL,
10022 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010023 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10024 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010025 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010026
10027 /*
10028 * 2 All simple type definitions must be derived ultimately from the ·simple
10029 * ur-type definition (so· circular definitions are disallowed). That is, it
10030 * must be possible to reach a built-in primitive datatype or the ·simple
10031 * ur-type definition· by repeatedly following the {base type definition}.
10032 */
10033 baseType = type->baseType;
10034 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10035 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10036 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10037 if (baseType == anySimpleType)
10038 break;
10039 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010040 xmlSchemaPCustomErr(ctxt,
10041 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10042 NULL, type, NULL,
10043 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010044 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10045 }
10046 baseType = baseType->baseType;
10047 }
10048 /*
10049 * 3 The {final} of the {base type definition} must not contain restriction.
10050 */
10051 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10052 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010053 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010054 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010055 NULL, type, NULL,
10056 "The 'final' of its base type %s must not contain "
10057 "'restriction'",
10058 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10059 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010060 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10061 }
10062 return (0);
10063}
10064
10065/**
10066 * xmlSchemaCheckDerivationValidSimpleRestriction:
10067 * @ctxt: the schema parser context
10068 * @type: the simple type definition
10069 *
10070 * Checks if the given @type (simpleType) is derived
10071 * validly by restriction.
10072 *
10073 * Returns -1 on internal errors, 0 if the type is validly derived,
10074 * a positive error code otherwise.
10075 */
10076static int
10077xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010078 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010079{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010080 xmlChar *str = NULL;
10081
10082 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010083
10084 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10085 xmlSchemaPErr(ctxt, type->node,
10086 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010087 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10088 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010089 type->name, NULL);
10090 return (-1);
10091 }
10092
10093 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10094 xmlSchemaTypePtr primitive;
10095 /*
10096 * 1.1 The {base type definition} must be an atomic simple
10097 * type definition or a built-in primitive datatype.
10098 */
10099 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010100 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010101 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010102 NULL, type, NULL,
10103 "The base type %s is not an atomic simple type",
10104 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10105 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010106 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10107 }
10108 /* 1.2 The {final} of the {base type definition} must not contain
10109 * restriction.
10110 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010111 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010112 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10113 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010114 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010115 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010116 NULL, type, NULL,
10117 "The final of its base type %s must not contain 'restriction'",
10118 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10119 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010120 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10121 }
10122
10123 /*
10124 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10125 * type definition}, as specified in the appropriate subsection of 3.2
10126 * Primitive datatypes.
10127 */
10128 if (type->facets != NULL) {
10129 xmlSchemaFacetPtr facet;
10130 int ok = 1;
10131
10132 primitive = xmlSchemaGetPrimitiveType(type);
10133 if (primitive == NULL) {
10134 xmlSchemaPErr(ctxt, type->node,
10135 XML_ERR_INTERNAL_ERROR,
10136 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010137 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010138 type->name, NULL);
10139 return (-1);
10140 }
10141 facet = type->facets;
10142 do {
10143 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010144 ok = 0;
10145 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010146 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010147 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010148 }
10149 facet = facet->next;
10150 } while (facet != NULL);
10151 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010152 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010153 }
10154 /*
10155 * TODO: 1.3.2 (facet derivation)
10156 */
10157 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10158 xmlSchemaTypePtr itemType = NULL;
10159
10160 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10161 if (itemType == NULL) {
10162 xmlSchemaPErr(ctxt, type->node,
10163 XML_ERR_INTERNAL_ERROR,
10164 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010165 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010166 type->name, NULL);
10167 return (-1);
10168 }
10169 /*
10170 * 2.1 The {item type definition} must have a {variety} of atomic or
10171 * union (in which case all the {member type definitions}
10172 * must be atomic).
10173 */
10174 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10175 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010176 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010177 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010178 NULL, type, NULL,
10179 "The item type %s must have a variety of atomic or union",
10180 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10181 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010182 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10183 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10184 xmlSchemaTypeLinkPtr member;
10185
10186 member = itemType->memberTypes;
10187 while (member != NULL) {
10188 if ((member->type->flags &
10189 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010190 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010191 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010192 NULL, type, NULL,
10193 "The item type is a union type, but the "
10194 "member type %s of this item type is not atomic",
10195 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10196 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010197 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10198 }
10199 member = member->next;
10200 }
10201 }
10202
10203 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10204 xmlSchemaFacetPtr facet;
10205 /*
10206 * This is the case if we have: <simpleType><list ..
10207 */
10208 /*
10209 * 2.3.1
10210 * 2.3.1.1 The {final} of the {item type definition} must not
10211 * contain list.
10212 */
10213 if (xmlSchemaTypeFinalContains(ctxt->schema,
10214 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010215 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010216 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010217 NULL, type, NULL,
10218 "The final of its item type %s must not contain 'list'",
10219 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10220 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010221 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10222 }
10223 /*
10224 * 2.3.1.2 The {facets} must only contain the whiteSpace
10225 * facet component.
10226 */
10227 if (type->facets != NULL) {
10228 facet = type->facets;
10229 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010230 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10231 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010232 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010233 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010234 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10235 }
10236 facet = facet->next;
10237 } while (facet != NULL);
10238 }
10239 /*
10240 * TODO: Datatypes states:
10241 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10242 * whose ·lexical space· allows space (such as string or anyURI)or
10243 * a ·union· datatype any of whose {member type definitions}'s
10244 * ·lexical space· allows space.
10245 */
10246 } else {
10247 /*
10248 * This is the case if we have: <simpleType><restriction ...
10249 */
10250 /*
10251 * 2.3.2
10252 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10253 */
10254 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010255 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010256 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010257 NULL, type, NULL,
10258 "The base type %s must be a list type",
10259 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10260 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010261 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10262 }
10263 /*
10264 * 2.3.2.2 The {final} of the {base type definition} must not
10265 * contain restriction.
10266 */
10267 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10268 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010269 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010270 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010271 NULL, type, NULL,
10272 "The final of the base type %s must not contain 'restriction'",
10273 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10274 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010275 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10276 }
10277 /*
10278 * 2.3.2.3 The {item type definition} must be validly derived
10279 * from the {base type definition}'s {item type definition} given
10280 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10281 */
10282 {
10283 xmlSchemaTypePtr baseItemType;
10284
10285 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
10286 if (baseItemType == NULL) {
10287 xmlSchemaPErr(ctxt, type->node,
10288 XML_ERR_INTERNAL_ERROR,
10289 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010290 "List simple type '%s': Failed to "
10291 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010292 type->name, type->baseType->name);
10293 return (-1);
10294 }
10295 if ((itemType != baseItemType) &&
10296 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
10297 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010298 xmlChar *strBIT = NULL, *strBT = NULL;
10299 xmlSchemaPCustomErrExt(ctxt,
10300 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
10301 NULL, type, NULL,
10302 "The item type %s is not validly derived from the "
10303 "item type %s of the base type %s",
10304 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
10305 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
10306 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10307
10308 FREE_AND_NULL(str)
10309 FREE_AND_NULL(strBIT)
10310 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010311 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
10312 }
10313 }
10314
10315 if (type->facets != NULL) {
10316 xmlSchemaFacetPtr facet;
10317 int ok = 1;
10318 /*
10319 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
10320 * and enumeration facet components are allowed among the {facets}.
10321 */
10322 facet = type->facets;
10323 do {
10324 switch (facet->type) {
10325 case XML_SCHEMA_FACET_LENGTH:
10326 case XML_SCHEMA_FACET_MINLENGTH:
10327 case XML_SCHEMA_FACET_MAXLENGTH:
10328 case XML_SCHEMA_FACET_WHITESPACE:
10329 /*
10330 * TODO: 2.5.1.2 List datatypes
10331 * The value of ·whiteSpace· is fixed to the value collapse.
10332 */
10333 case XML_SCHEMA_FACET_PATTERN:
10334 case XML_SCHEMA_FACET_ENUMERATION:
10335 break;
10336 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010337 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010338 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010339 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010340 /*
10341 * We could return, but it's nicer to report all
10342 * invalid facets.
10343 */
10344 ok = 0;
10345 }
10346 }
10347 facet = facet->next;
10348 } while (facet != NULL);
10349 if (ok == 0)
10350 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
10351 /*
10352 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
10353 * is a facet of the same kind in the {facets} of the {base type
10354 * definition} (call this BF),then the DF's {value} must be a valid
10355 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
10356 */
10357 }
10358
10359
10360 }
10361 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10362 /*
10363 * 3.1 The {member type definitions} must all have {variety} of
10364 * atomic or list.
10365 */
10366 xmlSchemaTypeLinkPtr member;
10367
10368 member = type->memberTypes;
10369 while (member != NULL) {
10370 if (((member->type->flags &
10371 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10372 ((member->type->flags &
10373 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010374 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010375 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010376 NULL, type, NULL,
10377 "The member type %s is neither an atomic, nor a list type",
10378 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10379 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010380 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
10381 }
10382 member = member->next;
10383 }
10384 /*
10385 * 3.3.1 If the {base type definition} is the ·simple ur-type
10386 * definition·
10387 */
10388 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10389 /*
10390 * 3.3.1.1 All of the {member type definitions} must have a
10391 * {final} which does not contain union.
10392 */
10393 member = type->memberTypes;
10394 while (member != NULL) {
10395 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
10396 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010397 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010398 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010399 NULL, type, NULL,
10400 "The final of member type %s contains 'union'",
10401 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10402 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010403 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
10404 }
10405 member = member->next;
10406 }
10407 /*
10408 * 3.3.1.2 The {facets} must be empty.
10409 */
10410 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010411 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010412 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010413 NULL, type, NULL,
10414 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010415 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
10416 }
10417 } else {
10418 /*
10419 * 3.3.2.1 The {base type definition} must have a {variety} of union.
10420 */
10421 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010422 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010423 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010424 NULL, type, NULL,
10425 "The base type %s is not a union type",
10426 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10427 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010428 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
10429 }
10430 /*
10431 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
10432 */
10433 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10434 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010435 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010436 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010437 NULL, type, NULL,
10438 "The final of its base type %s must not contain 'restriction'",
10439 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10440 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010441 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
10442 }
10443 /*
10444 * 3.3.2.3 The {member type definitions}, in order, must be validly
10445 * derived from the corresponding type definitions in the {base
10446 * type definition}'s {member type definitions} given the empty set,
10447 * as defined in Type Derivation OK (Simple) (§3.14.6).
10448 */
10449 {
10450 xmlSchemaTypeLinkPtr baseMember;
10451
10452 /*
10453 * OPTIMIZE: if the type is restricting, it has no local defined
10454 * member types and inherits the member types of the base type;
10455 * thus a check for equality can be skipped.
10456 */
10457 /*
10458 * TODO: Even worse: I cannot see a scenario where a restricting
10459 * union simple type can have other member types as the member
10460 * types of it's base type. This check seems not necessary with
10461 * respect to the derivation process in libxml2.
10462 */
10463 if (type->memberTypes != NULL) {
10464 member = type->memberTypes;
10465 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
10466 if ((member == NULL) && (baseMember != NULL)) {
10467 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010468 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010469 "Internal error: "
10470 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010471 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010472 "of member types in the base type\n",
10473 type->name, NULL);
10474 }
10475 while (member != NULL) {
10476 if (baseMember == NULL) {
10477 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010478 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010479 "Internal error: "
10480 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010481 "(3.3.2.3), union simple type '%s', unequal number "
10482 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010483 type->name, NULL);
10484 }
10485 if ((member->type != baseMember->type) &&
10486 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
10487 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010488 xmlChar *strBMT = NULL, *strBT = NULL;
10489
10490 xmlSchemaPCustomErrExt(ctxt,
10491 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
10492 NULL, type, NULL,
10493 "The member type %s is not validly derived from its "
10494 "corresponding member type %s of the base type %s",
10495 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
10496 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
10497 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10498 FREE_AND_NULL(str)
10499 FREE_AND_NULL(strBMT)
10500 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010501 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
10502 }
10503 member = member->next;
10504 baseMember = baseMember->next;
10505 }
10506 }
10507 }
10508 /*
10509 * 3.3.2.4 Only pattern and enumeration facet components are
10510 * allowed among the {facets}.
10511 */
10512 if (type->facets != NULL) {
10513 xmlSchemaFacetPtr facet;
10514 int ok = 1;
10515
10516 facet = type->facets;
10517 do {
10518 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
10519 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010520 xmlSchemaPIllegalFacetListUnionErr(ctxt,
10521 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
10522 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010523 ok = 0;
10524 }
10525 facet = facet->next;
10526 } while (facet != NULL);
10527 if (ok == 0)
10528 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
10529
10530 }
10531 /*
10532 * TODO: 3.3.2.5 (facet derivation)
10533 */
10534 }
10535 }
10536
10537 return (0);
10538}
10539
10540/**
10541 * xmlSchemaCheckSRCSimpleType:
10542 * @ctxt: the schema parser context
10543 * @type: the simple type definition
10544 *
10545 * Checks crc-simple-type constraints.
10546 *
10547 * Returns 0 if the constraints are satisfied,
10548 * if not a positive error code and -1 on internal
10549 * errors.
10550 */
10551static int
10552xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
10553 xmlSchemaTypePtr type)
10554{
10555 /*
10556 * NOTE: src-simple-type 2-4 are redundant, since the checks
10557 * were are done for the corresponding <restriction>, <list> and <union>
10558 * elements, but W3C wants a <simpleType> error as well, so it gets one.
10559 * Maby this can be skipped in the future, if we get sure it's not needed.
10560 */
10561 if (type->subtypes == NULL) {
10562 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010563 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010564 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010565 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010566 type->name, NULL);
10567 return (-1);
10568 }
10569 /*
10570 * src-simple-type.1 The corresponding simple type definition, if any,
10571 * must satisfy the conditions set out in Constraints on Simple Type
10572 * Definition Schema Components (§3.14.6).
10573 */
10574 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
10575 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
10576 /*
10577 * TODO: Removed this, since it got annoying to get an
10578 * extra error report, if anything failed until now.
10579 * Enable this if needed.
10580 */
10581 /*
10582 xmlSchemaPErr(ctxt, type->node,
10583 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010584 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010585 "on simple type definitions.\n",
10586 type->name, NULL);
10587 */
10588 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
10589 }
10590
10591 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
10592 /*
10593 * src-simple-type.2 If the <restriction> alternative is chosen,
10594 * either it must have a base [attribute] or a <simpleType> among its
10595 * [children], but not both.
10596 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010597 /*
10598 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
10599 * NOTE: This was removed, since this will be already handled
10600 * in the parse function for <restriction>.
10601 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010602 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
10603 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
10604 * an itemType [attribute] or a <simpleType> among its [children],
10605 * but not both.
10606 * NOTE: baseType is set to the local simple type definiton,
10607 * if existent, at parse time. This is a hack and not nice.
10608 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010609 /*
10610 * TODO: Remove this, and add the check to the parse function of <list>.
10611 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010612 if (((type->subtypes->base == NULL) &&
10613 (type->baseType == NULL)) ||
10614 ((type->subtypes->base != NULL) &&
10615 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010616 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010617 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010618 NULL, type, NULL,
10619 "Either the attribute 'itemType' or the <simpleType> child "
10620 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010621 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
10622 }
10623
10624
10625 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
10626 xmlSchemaTypeLinkPtr member;
10627 xmlSchemaTypePtr ancestor, anySimpleType;
10628
10629 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10630
10631 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
10632 * the <union> alternative is chosen, there must not be any entries
10633 * in the memberTypes [attribute] at any depth which resolve to the
10634 * component corresponding to the <simpleType>.
10635 */
10636 member = type->memberTypes;
10637 while (member != NULL) {
10638 ancestor = member->type;
10639 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
10640 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10641 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
10642 if (ancestor == anySimpleType)
10643 break;
10644 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010645 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010646 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010647 NULL, type, NULL,
10648 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010649 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
10650 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10651 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000010652 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000010653 * type as item type, which in turn has a list ST as member
10654 * type, we will assume this here as well, since this check
10655 * was not yet performed.
10656 */
10657
10658 }
10659 ancestor = ancestor->baseType;
10660 }
10661 member = member->next;
10662 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010663 }
10664
10665 return (0);
10666}
10667
William M. Brack2f2a6632004-08-20 23:09:47 +000010668#if 0 /* Not yet used code for CT schema validation */
10669static int
10670xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
10671 const xmlChar * value,
10672 xmlSchemaTypePtr type,
10673 int fireErrors)
10674{
10675 int ret;
10676 /*
10677 * 3.14.4 Simple Type Definition Validation Rules
10678 * Validation Rule: String Valid
10679 */
10680 /*
10681 * 1 It is schema-valid with respect to that definition as defined
10682 * by Datatype Valid in [XML Schemas: Datatypes].
10683 */
10684 ctxt->type = type;
10685 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, fireErrors, 1, 1);
10686 return (ret);
10687 /*
10688 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
10689 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
10690 * the string must be a ·declared entity name·.
10691 */
10692 /*
10693 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
10694 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
10695 * then every whitespace-delimited substring of the string must be a ·declared
10696 * entity name·.
10697 */
10698 /*
10699 * 2.3 otherwise no further condition applies.
10700 */
10701
10702 return (0);
10703}
10704
10705
10706static int
10707xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr ctxt,
10708 xmlSchemaElementPtr elemDecl)
10709{
10710 xmlSchemaTypePtr typeDef;
10711 if (elemDecl->value == NULL)
10712 return (0);
10713 if (elemDecl->subtypes == NULL) {
10714 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010715 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010716 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
10717 "Internal error: xmlSchemaCheckCOSValidDefault, "
10718 "the element decl. '%s' has no type assigned", elemDecl->name);
10719 return (-1);
10720 }
10721 typeDef = elemDecl->subtypes;
10722 if ((typeDef->type == XML_SCHEMA_TYPE_SIMPLE) ||
10723 ((typeDef->type == XML_SCHEMA_TYPE_COMPLEX) &&
10724 ((typeDef->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10725 (typeDef->contentType == XML_SCHEMA_CONTENT_BASIC)))) {
10726 xmlSchemaValidCtxtPtr vctxt;
10727 xmlAttrPtr attr;
10728 int ret = 0;
10729 /*
10730 * 1 If the type definition is a simple type definition, then the string
10731 * must be ·valid· with respect to that definition as defined by String
10732 * Valid (§3.14.4).
10733 */
10734 /*
10735 * 2.2.1 If the {content type} is a simple type definition, then the
10736 * string must be ·valid· with respect to that simple type definition
10737 * as defined by String Valid (§3.14.4).
10738 */
10739 /*
10740 * TODO: ?
10741 */
10742
10743 vctxt = xmlSchemaNewValidCtxt(NULL);
10744 if (vctxt == NULL) {
10745 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010746 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010747 "Internal error: xmlSchemaCheckCOSValidDefault, "
10748 "creation of a new validation context failed.\n",
10749 NULL, NULL);
10750 return (-1);
10751 }
10752 /*
10753 * TODO: This won't work.
10754 */
10755 if (typeDef->type == XML_SCHEMA_TYPE_SIMPLE)
10756 ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0);
10757 if (ret > 0) {
10758 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10759 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10760 else
10761 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10762 if (ctxt != NULL) {
10763 xmlSchemaPSimpleTypeErr(ctxt,
10764 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10765 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10766 elemDecl->subtypes, NULL, elemDecl->value,
10767 NULL, NULL, NULL);
10768 return (ctxt->err);
10769 }
10770 ret = ctxt->err;
10771 } else if (ret < 0) {
10772 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010773 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010774 "Internal error: xmlSchemaCheckCOSValidDefault, "
10775 "while validating the default/fixed value.\n",
10776 NULL, NULL);
10777 }
10778 xmlSchemaFreeValidCtxt(vctxt);
10779 return (ret);
10780 } else {
10781 /*
10782 * Complex type.
10783 *
10784 * 2.1 its {content type} must be a simple type definition or mixed.
10785 */
10786 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10787 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC) &&
10788 (elemDecl->subtypes->contentType == XML_SCHEMA_CONTENT_MIXED)) {
10789 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10790 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
10791 "The content type must be a simple type definition or mixed.",
10792 NULL);
10793 return(ctxt->err);
10794 }
10795 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10796 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC)) {
10797 xmlSchemaValidCtxtPtr vctxt;
10798 xmlAttrPtr attr;
10799 int ret;
10800
10801 /* TODO: Avoid creation of a new context. */
10802 vctxt = xmlSchemaNewValidCtxt(NULL);
10803 if (vctxt == NULL) {
10804 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010805 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010806 "Internal error: xmlSchemaCheckCOSValidDefault, "
10807 "creation of a new validation context failed.\n",
10808 NULL, NULL);
10809 return (-1);
10810 }
10811 vctxt->type = elemDecl->subtypes;
10812 ret = xmlSchemaValidateSimpleTypeValue(vctxt, elemDecl->value, 0, 1, 1);
10813 if (ret > 0) {
10814 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10815 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10816 else
10817 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10818 if (ctxt != NULL) {
10819 xmlSchemaPSimpleTypeErr(ctxt,
10820 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10821 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10822 elemDecl->subtypes, NULL, elemDecl->value,
10823 NULL, NULL, NULL);
10824 return (ctxt->err);
10825 }
10826 ret = ctxt->err;
10827 } else if (ret < 0) {
10828 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010829 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010830 "Internal error: xmlSchemaCheckCOSValidDefault, "
10831 "while validating the default/fixed value.\n",
10832 NULL, NULL);
10833 }
10834 xmlSchemaFreeValidCtxt(vctxt);
10835 return (ret);
10836 } else {
10837 /*
10838 * 2.2.2 If the {content type} is mixed, then the {content type}'s
10839 * particle must be ·emptiable· as defined by Particle Emptiable
10840 * (§3.9.6).
10841 */
10842 /*
10843 * TODO: Implement this.
10844 */
10845 }
10846 }
10847
10848 return (0);
10849}
10850
10851/**
10852 * xmlSchemaGetSTContentOfCT:
10853 * @ctxt: the schema parser context
10854 * @type: the complex type definition
10855 *
10856 *
10857 * Returns the corresponding simple type for the content of
10858 * the complex type.
10859 */
10860static xmlSchemaTypePtr
10861xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
10862 xmlSchemaTypePtr type)
10863{
10864 xmlSchemaTypePtr orig = type, anyType;
10865
10866 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10867 while ((type != NULL) && (type != anyType) &&
10868 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10869 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
10870 return(type);
10871 type = type->baseType;
10872 }
10873 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010874 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010875 NULL, orig, NULL,
10876 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
10877 "no simple type for the content of complex type '%s' could be "
10878 "computed", orig->name);
10879 return (NULL);
10880}
10881
10882
10883static xmlSchemaTypePtr
10884xmlSchemaGetContentType(xmlSchemaParserCtxtPtr ctxt,
10885 xmlSchemaTypePtr type)
10886{
10887 if (type->baseType == NULL) {
10888 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010889 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010890 NULL, type, NULL,
10891 "Internal error: xmlSchemaGetContentType, "
10892 "the complex type '%s' has no base type", type->name);
10893 return (NULL);
10894 }
10895 if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
10896 if ((type->baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10897 ((type->baseType->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10898 (type->baseType->contentType == XML_SCHEMA_CONTENT_BASIC)) &&
10899 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
10900 /*
10901 * 1 If the type definition ·resolved· to by the ·actual value· of
10902 * the base [attribute] is a complex type definition whose own
10903 * {content type} is a simple type definition and the <restriction>
10904 * alternative is chosen
10905 */
10906
10907
10908 }
10909 } else {
10910
10911 }
10912}
10913
10914/**
10915 * xmlSchemaCheckCOSCTExtends:
10916 * @ctxt: the schema parser context
10917 * @type: the complex type definition
10918 *
10919 * Schema Component Constraint: Derivation Valid (Extension)
10920 *
10921 * Returns 0 if the constraints are satisfied, a positive
10922 * error code if not and -1 if an internal error occured.
10923 */
10924static int
10925xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
10926 xmlSchemaTypePtr type)
10927{
10928 xmlSchemaTypePtr base;
10929 /*
10930 * 1 If the {base type definition} is a complex type definition,
10931 * then all of the following must be true:
10932 */
10933 base = type->baseType;
10934 if (base == NULL) {
10935 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010936 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010937 NULL, type, NULL,
10938 "Internal error: xmlSchemaCheckCOSCTExtends, "
10939 "the complex type '%s' has no base type", type->name);
10940 return (-1);
10941 }
10942 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
10943 /*
10944 * 1.1 The {final} of the {base type definition} must not
10945 * contain extension.
10946 */
10947 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
10948 xmlSchemaPCustomErr(ctxt,
10949 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
10950 NULL, type, NULL,
10951 "The 'final' of the base type definition "
10952 "contains extension", NULL);
10953 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
10954 }
10955 /*
10956 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
10957 * of the complex type definition itself, that is, for every attribute
10958 * use in the {attribute uses} of the {base type definition}, there
10959 * must be an attribute use in the {attribute uses} of the complex
10960 * type definition itself whose {attribute declaration} has the same
10961 * {name}, {target namespace} and {type definition} as its attribute
10962 * declaration
10963 *
10964 * NOTE: This will be already satisfied by the way the attribute uses
10965 * are extended in xmlSchemaBuildAttributeValidation; thus this check
10966 * is not needed.
10967 */
10968
10969 /*
10970 * 1.3 If it has an {attribute wildcard}, the complex type definition
10971 * must also have one, and the base type definition's {attribute
10972 * wildcard}'s {namespace constraint} must be a subset of the complex
10973 * type definition's {attribute wildcard}'s {namespace constraint},
10974 * as defined by Wildcard Subset (§3.10.6).
10975 *
10976 * This is already checked in xmlSchemaBuildAttributeValidation; thus
10977 * this check is not needed.
10978 */
10979
10980 /*
10981 * 1.4 One of the following must be true:
10982 *
10983 * 1.4.1 The {content type} of the {base type definition} and the
10984 * {content type} of the complex type definition itself must be the same
10985 * simple type definition
10986 */
10987
10988
10989
10990 } else {
10991 /*
10992 * 2 If the {base type definition} is a simple type definition,
10993 * then all of the following must be true:
10994 */
10995 /*
10996 * 2.1 The {content type} must be the same simple type definition.
10997 */
10998 /*
10999 * 2.2 The {final} of the {base type definition} must not contain
11000 * extension
11001 */
11002 }
11003
11004}
11005
11006#endif
11007
Daniel Veillard01fa6152004-06-29 17:04:39 +000011008/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011009 * xmlSchemaGroupDefFixup:
11010 * @typeDecl: the schema model group definition
11011 * @ctxt: the schema parser context
11012 *
11013 * Fixes model group definitions.
11014 */
11015static void
11016xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11017 xmlSchemaParserCtxtPtr ctxt,
11018 const xmlChar * name ATTRIBUTE_UNUSED)
11019{
11020 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11021 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11022 xmlSchemaTypePtr groupDef;
11023 /*
11024 * Resolve the reference.
11025 */
11026 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11027 group->refNs);
11028 if (groupDef == NULL) {
11029 xmlSchemaPResCompAttrErr(ctxt,
11030 XML_SCHEMAP_SRC_RESOLVE,
11031 NULL, group, NULL,
11032 "ref", group->ref, group->refNs,
11033 XML_SCHEMA_TYPE_GROUP, NULL);
11034 return;
11035 }
11036 group->subtypes = groupDef;
11037 }
11038}
11039
11040/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011041 * xmlSchemaTypeFixup:
11042 * @typeDecl: the schema type definition
11043 * @ctxt: the schema parser context
11044 *
11045 * Fixes the content model of the type.
11046 */
11047static void
11048xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011049 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011050{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011051 xmlSchemaTypePtr ctxtType;
11052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000011053 if (typeDecl == NULL)
11054 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011055 /*
11056 * Do not allow the following types to be typefixed, prior to
11057 * the corresponding simple/complex types.
11058 */
11059 if (ctxt->ctxtType == NULL) {
11060 switch (typeDecl->type) {
11061 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
11062 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
11063 case XML_SCHEMA_TYPE_UNION:
11064 case XML_SCHEMA_TYPE_RESTRICTION:
11065 case XML_SCHEMA_TYPE_EXTENSION:
11066 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011067 default:
11068 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011069 }
11070 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011071 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011072 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000011073 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011074 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011075 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
11076 if (typeDecl->subtypes != NULL) {
11077 if (typeDecl->subtypes->contentType ==
11078 XML_SCHEMA_CONTENT_UNKNOWN) {
11079 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
11080 NULL);
11081 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011082 typeDecl->contentType =
11083 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011084 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011085 break;
11086 }
11087 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011088 xmlSchemaTypePtr base = NULL;
11089
11090 ctxt->ctxtType->flags |=
11091 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
William M. Brack2f2a6632004-08-20 23:09:47 +000011092 if (typeDecl->baseType != NULL)
11093 base = typeDecl->baseType;
11094 else if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011095 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011096 xmlSchemaGetType(ctxt->schema, typeDecl->base,
11097 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011098 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 xmlSchemaPResCompAttrErr(ctxt,
11100 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000011101 NULL, NULL,
11102 (xmlNodePtr) xmlSchemaGetPropNode(typeDecl->node, "base"),
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 "base", typeDecl->base, typeDecl->baseNs,
11104 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011105 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000011106 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011107 xmlSchemaTypeFixup(base, ctxt, NULL);
11108 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011109 }
11110 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011111 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
11112 /*
11113 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000011114 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011115 /*
11116 * Content type.
11117 */
11118 if (typeDecl->subtypes == NULL)
11119 /* 1.1.1 */
11120 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11121 else if ((typeDecl->subtypes->subtypes == NULL) &&
11122 ((typeDecl->subtypes->type ==
11123 XML_SCHEMA_TYPE_ALL)
11124 || (typeDecl->subtypes->type ==
11125 XML_SCHEMA_TYPE_SEQUENCE)))
11126 /* 1.1.2 */
11127 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11128 else if ((typeDecl->subtypes->type ==
11129 XML_SCHEMA_TYPE_CHOICE)
11130 && (typeDecl->subtypes->subtypes == NULL))
11131 /* 1.1.3 */
11132 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
11133 else {
11134 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011135 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011136 XML_SCHEMA_CONTENT_ELEMENTS;
11137 }
11138 } else {
11139 /*
11140 * SimpleType restriction.
11141 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011142 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011143 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011144 break;
11145 }
11146 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011147 xmlSchemaTypePtr base = NULL;
11148 xmlSchemaContentType explicitContentType;
11149
11150 /*
11151 * An extension does exist on a complexType only.
11152 */
11153 ctxt->ctxtType->flags |=
11154 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11155 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011156 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011157 xmlSchemaPCustomErr(ctxt,
11158 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
11159 NULL, typeDecl, typeDecl->node,
11160 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000011161 return;
11162 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011163 if (typeDecl->base != NULL) {
11164 base =
11165 xmlSchemaGetType(ctxt->schema, typeDecl->base,
11166 typeDecl->baseNs);
11167 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011168 xmlSchemaPResCompAttrErr(ctxt,
11169 XML_SCHEMAP_SRC_RESOLVE,
11170 NULL, typeDecl, typeDecl->node,
11171 "base", typeDecl->base, typeDecl->baseNs,
11172 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011173 } else if (base->contentType ==
11174 XML_SCHEMA_CONTENT_UNKNOWN) {
11175 typeDecl->recurse = 1;
11176 xmlSchemaTypeFixup(base, ctxt, NULL);
11177 typeDecl->recurse = 0;
11178 }
11179 /*
11180 * The type definition ·resolved· to by the ·actual
11181 * value· of the base [attribute]
11182 */
11183 ctxt->ctxtType->baseType = base;
11184 /*
11185 * TODO: This one is still needed for computation of
11186 * the content model by xmlSchemaBuildAContentModel.
11187 * Try to get rid of it.
11188 */
11189 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011191 if ((typeDecl->subtypes != NULL) &&
11192 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
11193 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
11194
11195 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
11196 if (typeDecl->subtypes == NULL)
11197 /* 1.1.1 */
11198 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11199 else if ((typeDecl->subtypes->subtypes == NULL) &&
11200 ((typeDecl->subtypes->type ==
11201 XML_SCHEMA_TYPE_ALL)
11202 || (typeDecl->subtypes->type ==
11203 XML_SCHEMA_TYPE_SEQUENCE)))
11204 /* 1.1.2 */
11205 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11206 else if ((typeDecl->subtypes->type ==
11207 XML_SCHEMA_TYPE_CHOICE)
11208 && (typeDecl->subtypes->subtypes == NULL))
11209 /* 1.1.3 */
11210 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11211 if (base != NULL) {
11212 /* It will be reported later, if the base is missing. */
11213 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
11214 /* 2.1 */
11215 typeDecl->contentType = base->contentType;
11216 } else if (base->contentType ==
11217 XML_SCHEMA_CONTENT_EMPTY) {
11218 /* 2.2 imbitable ! */
11219 typeDecl->contentType =
11220 XML_SCHEMA_CONTENT_ELEMENTS;
11221 } else {
11222 /* 2.3 imbitable pareil ! */
11223 typeDecl->contentType =
11224 XML_SCHEMA_CONTENT_ELEMENTS;
11225 }
11226 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 break;
11228 }
11229 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011230 ctxtType = ctxt->ctxtType;
11231 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011232 if ((typeDecl->subtypes == NULL) ||
11233 ((typeDecl->subtypes->type !=
11234 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
11235 (typeDecl->subtypes->type !=
11236 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
11237 /*
11238 * This case is understood as shorthand for complex
11239 * content restricting the ur-type definition, and
11240 * the details of the mappings should be modified as
11241 * necessary.
11242 */
11243 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11244 typeDecl->flags |=
11245 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11246 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011248 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011249 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11250 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011251 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011252 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011253 if ((typeDecl->subtypes != NULL) &&
11254 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011255 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011256 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011257 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011258 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011259 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011260 typeDecl->contentType =
11261 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011262 } else {
11263 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011264 typeDecl->contentType =
11265 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011266 }
11267 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011268 }
11269 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011270 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 break;
11272 }
11273 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
11274 if (typeDecl->subtypes == NULL) {
11275 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011276 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11277 typeDecl->contentType =
11278 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011279 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011280 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 typeDecl->contentType =
11282 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000011283 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011284 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
11285 NULL);
11286 if (typeDecl->subtypes != NULL)
11287 typeDecl->contentType =
11288 typeDecl->subtypes->contentType;
11289 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011290 /*
11291 * Removed due to implementation of the build of attribute uses.
11292 */
11293 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011294 if (typeDecl->attributes == NULL)
11295 typeDecl->attributes =
11296 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011297 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 }
11299 break;
11300 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011301 case XML_SCHEMA_TYPE_SIMPLE:
11302 /*
11303 * Simple Type Definition Schema Component
11304 *
11305 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011306 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011307 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11308 if (typeDecl->subtypes->contentType ==
11309 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011310 ctxt->ctxtType = typeDecl;
11311 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011312 }
11313 /* Fixup base type */
11314 if ((typeDecl->baseType != NULL) &&
11315 (typeDecl->baseType->contentType ==
11316 XML_SCHEMA_CONTENT_UNKNOWN)) {
11317 /* OPTIMIZE: Actually this one will never by hit, since
11318 * the base type is already type-fixed in <restriction>.
11319 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011320 ctxt->ctxtType = typeDecl;
11321 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011322 }
11323 /* Base type:
11324 * 2 If the <list> or <union> alternative is chosen,
11325 * then the ·simple ur-type definition·.
11326 */
11327 if (typeDecl->subtypes->type ==
11328 XML_SCHEMA_TYPE_LIST) {
11329 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11330 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11331 } else if (typeDecl->subtypes->type ==
11332 XML_SCHEMA_TYPE_UNION) {
11333 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11334 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11335 } else if (typeDecl->subtypes->type ==
11336 XML_SCHEMA_TYPE_RESTRICTION) {
11337 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
11338
11339 /*
11340 * Variety
11341 * If the <restriction> alternative is chosen, then the
11342 * {variety} of the {base type definition}.
11343 */
11344 if (typeDecl->baseType != NULL) {
11345 if (typeDecl->baseType->flags &
11346 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
11347 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
11348 else if (typeDecl->baseType->flags &
11349 XML_SCHEMAS_TYPE_VARIETY_LIST)
11350 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11351 else if (typeDecl->baseType->flags &
11352 XML_SCHEMAS_TYPE_VARIETY_UNION)
11353 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11354 /*
11355 * Schema Component Constraint: Simple Type Restriction
11356 * (Facets)
11357 * NOTE: Satisfaction of 1 and 2 arise from the fixup
11358 * applied beforehand.
11359 *
11360 * 3 The {facets} of R are the union of S and the {facets}
11361 * of B, eliminating duplicates. To eliminate duplicates,
11362 * when a facet of the same kind occurs in both S and the
11363 * {facets} of B, the one in the {facets} of B is not
11364 * included, with the exception of enumeration and pattern
11365 * facets, for which multiple occurrences with distinct values
11366 * are allowed.
11367 */
11368 if (typeDecl->baseType->facetSet != NULL) {
11369 last = typeDecl->facetSet;
11370 if (last != NULL)
11371 while (last->next != NULL)
11372 last = last->next;
11373 cur = typeDecl->baseType->facetSet;
11374 for (; cur != NULL; cur = cur->next) {
11375 /*
11376 * Base patterns won't be add here:
11377 * they are ORed in a type and
11378 * ANDed in derived types. This will
11379 * happed at validation level by
11380 * walking the base axis of the type.
11381 */
11382 if (cur->facet->type ==
11383 XML_SCHEMA_FACET_PATTERN)
11384 continue;
11385 facet = NULL;
11386 if ((typeDecl->facetSet != NULL) &&
11387 (cur->facet->type !=
11388 XML_SCHEMA_FACET_PATTERN) &&
11389 (cur->facet->type !=
11390 XML_SCHEMA_FACET_ENUMERATION)) {
11391 facet = typeDecl->facetSet;
11392 do {
11393 if (cur->facet->type ==
11394 facet->facet->type)
11395 break;
11396 facet = facet->next;
11397 } while (facet != NULL);
11398 }
11399 if (facet == NULL) {
11400 facet = (xmlSchemaFacetLinkPtr)
11401 xmlMalloc(sizeof(xmlSchemaFacetLink));
11402 if (facet == NULL) {
11403 xmlSchemaPErrMemory(ctxt,
11404 "fixing simpleType", NULL);
11405 return;
11406 }
11407 facet->facet = cur->facet;
11408 facet->next = NULL;
11409 if (last == NULL)
11410 typeDecl->facetSet = facet;
11411 else
11412 last->next = facet;
11413 last = facet;
11414 }
11415 }
11416 }
11417 }
11418 }
11419 /*
11420 * Check constraints.
11421 */
11422 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011423 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011424 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011425 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011426 case XML_SCHEMA_TYPE_ALL:
11427 case XML_SCHEMA_TYPE_CHOICE:
11428 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11429 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011430 case XML_SCHEMA_TYPE_GROUP:
11431 /*
11432 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
11433 */
11434 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011435 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +000011436 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011437 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11438 break;
11439 case XML_SCHEMA_TYPE_UNION:
11440 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
11441 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11442 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011443 case XML_SCHEMA_TYPE_BASIC:
11444 case XML_SCHEMA_TYPE_ANY:
11445 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011446 case XML_SCHEMA_TYPE_UR:
11447 case XML_SCHEMA_TYPE_ELEMENT:
11448 case XML_SCHEMA_TYPE_ATTRIBUTE:
11449 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000011450 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011451 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011452 case XML_SCHEMA_FACET_MININCLUSIVE:
11453 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11454 case XML_SCHEMA_FACET_MAXINCLUSIVE:
11455 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11456 case XML_SCHEMA_FACET_TOTALDIGITS:
11457 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11458 case XML_SCHEMA_FACET_PATTERN:
11459 case XML_SCHEMA_FACET_ENUMERATION:
11460 case XML_SCHEMA_FACET_WHITESPACE:
11461 case XML_SCHEMA_FACET_LENGTH:
11462 case XML_SCHEMA_FACET_MAXLENGTH:
11463 case XML_SCHEMA_FACET_MINLENGTH:
11464 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011465 if (typeDecl->subtypes != NULL)
11466 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011467 break;
11468 }
11469 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011470#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011471 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011472 xmlGenericError(xmlGenericErrorContext,
11473 "Type of %s : %s:%d :", name,
11474 typeDecl->node->doc->URL,
11475 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011476 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011477 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011478 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011479 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011480 case XML_SCHEMA_CONTENT_SIMPLE:
11481 xmlGenericError(xmlGenericErrorContext, "simple\n");
11482 break;
11483 case XML_SCHEMA_CONTENT_ELEMENTS:
11484 xmlGenericError(xmlGenericErrorContext, "elements\n");
11485 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011486 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011487 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
11488 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011489 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011490 xmlGenericError(xmlGenericErrorContext, "empty\n");
11491 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011492 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011493 xmlGenericError(xmlGenericErrorContext, "mixed\n");
11494 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011495 /* Removed, since not used. */
11496 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000011497 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011498 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
11499 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011500 */
Daniel Veillard8651f532002-04-17 09:06:27 +000011501 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011502 xmlGenericError(xmlGenericErrorContext, "basic\n");
11503 break;
11504 default:
11505 xmlGenericError(xmlGenericErrorContext,
11506 "not registered !!!\n");
11507 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011508 }
11509#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011510}
11511
11512/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011513 * xmlSchemaCheckFacet:
11514 * @facet: the facet
11515 * @typeDecl: the schema type definition
11516 * @ctxt: the schema parser context or NULL
11517 * @name: name of the type
11518 *
11519 * Checks the default values types, especially for facets
11520 *
11521 * Returns 0 if okay or -1 in cae of error
11522 */
11523int
11524xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011525 xmlSchemaTypePtr typeDecl,
11526 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011527{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000011528 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011529 int ret = 0;
11530
11531 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011532 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011533 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011534 }
11535 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011536 case XML_SCHEMA_FACET_MININCLUSIVE:
11537 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11538 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011539 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11540 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011541 /*
11542 * Okay we need to validate the value
11543 * at that point.
11544 */
11545 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011546 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011547
11548 /* 4.3.5.5 Constraints on enumeration Schema Components
11549 * Schema Component Constraint: enumeration valid restriction
11550 * It is an ·error· if any member of {value} is not in the
11551 * ·value space· of {base type definition}.
11552 *
11553 * minInclusive, maxInclusive, minExclusive, maxExclusive:
11554 * The value ·must· be in the
11555 * ·value space· of the ·base type·.
11556 */
11557 /*
11558 * This function is intended to deliver a compiled value
11559 * on the facet. In XML Schemas the type holding a facet,
11560 * cannot be a built-in type. Thus to ensure that other API
11561 * calls (relaxng) do work, if the given type is a built-in
11562 * type, we will assume that the given built-in type *is
11563 * already* the base type.
11564 */
11565 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
11566 base = typeDecl->baseType;
11567 if (base == NULL) {
11568 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011569 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011570 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011571 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011572 typeDecl->name, NULL);
11573 return (-1);
11574 }
11575 } else
11576 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011577 /*
11578 * TODO: Try to avoid creating a new context.
11579 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011580 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011581 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011582 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011583 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011584 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011585 "creating a new validation context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011586 NULL, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011587 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011588 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011589 vctxt->type = base;
11590 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011591 facet->val = vctxt->value;
11592 vctxt->value = NULL;
11593 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011594 /* error code */
11595 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011596 xmlSchemaPErrExt(ctxt, facet->node,
11597 XML_SCHEMAP_INVALID_FACET,
11598 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011599 "Type definition '%s': The value '%s' of the "
11600 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011601 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011602 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011603 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011604 }
11605 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011606 } else if (ret < 0) {
11607 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011608 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011609 NULL, NULL, NULL,
11610 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011611 "failed to validate the value '%s' name of the "
11612 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011613 facet->value,
11614 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
11615 base->name, NULL, NULL);
11616 ret = -1;
11617 }
11618 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011619 break;
11620 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011621 case XML_SCHEMA_FACET_PATTERN:
11622 facet->regexp = xmlRegexpCompile(facet->value);
11623 if (facet->regexp == NULL) {
11624 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011625 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011626 "Type definition '%s': The value '%s' of the "
11627 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011628 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011629 ret = -1;
11630 }
11631 break;
11632 case XML_SCHEMA_FACET_TOTALDIGITS:
11633 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11634 case XML_SCHEMA_FACET_LENGTH:
11635 case XML_SCHEMA_FACET_MAXLENGTH:
11636 case XML_SCHEMA_FACET_MINLENGTH:{
11637 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011638
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011639 tmp =
11640 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
11641 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000011642 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011643 if (tmp != 0) {
11644 /* error code */
11645 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 xmlSchemaPErrExt(ctxt, facet->node,
11647 XML_SCHEMAP_INVALID_FACET_VALUE,
11648 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011649 "Type definition '%s': The value '%s' of the "
11650 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011651 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011652 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011653 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011654 }
11655 ret = -1;
11656 }
11657 break;
11658 }
11659 case XML_SCHEMA_FACET_WHITESPACE:{
11660 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
11661 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
11662 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
11663 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
11664 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
11665 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
11666 } else {
11667 if (ctxt != NULL) {
11668 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011669 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011670 "Type definition '%s': The value '%s' of the "
11671 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011672 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011673 }
11674 ret = -1;
11675 }
11676 }
11677 default:
11678 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011679 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011680 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011681}
11682
11683/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011684 * xmlSchemaCheckDefaults:
11685 * @typeDecl: the schema type definition
11686 * @ctxt: the schema parser context
11687 *
11688 * Checks the default values types, especially for facets
11689 */
11690static void
11691xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011692 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011693{
Daniel Veillard4255d502002-04-16 15:50:10 +000011694 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011695 name = typeDecl->name;
11696 /*
11697 * NOTE: It is intended to use the facets list, instead
11698 * of facetSet.
11699 */
11700 if (typeDecl->facets != NULL) {
11701 xmlSchemaFacetPtr facet = typeDecl->facets;
11702
11703 while (facet != NULL) {
11704 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
11705 facet = facet->next;
11706 }
11707 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011708}
11709
11710/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011711 * xmlSchemaGetCircModelGrDefRef:
11712 * @ctxtGr: the searched model group
11713 * @list: the list of model groups to be processed
11714 *
11715 * This one is intended to be used by
11716 * xmlSchemaCheckGroupDefCircular only.
11717 *
11718 * Returns the circular model group definition reference, otherwise NULL.
11719 */
11720static xmlSchemaTypePtr
11721xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
11722 xmlSchemaTypePtr gr)
11723{
11724 xmlSchemaTypePtr circ = NULL;
11725 int marked;
11726 /*
11727 * We will search for an model group reference which
11728 * references the context model group definition.
11729 */
11730 while (gr != NULL) {
11731 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
11732 (gr->type == XML_SCHEMA_TYPE_ALL) ||
11733 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
11734 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
11735 (gr->subtypes != NULL)) {
11736 marked = 0;
11737 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
11738 (gr->ref != NULL)) {
11739 if (gr->subtypes == ctxtGrDef)
11740 return (gr);
11741 else if (gr->subtypes->flags &
11742 XML_SCHEMAS_TYPE_MARKED) {
11743 gr = gr->next;
11744 continue;
11745 } else {
11746 /*
11747 * Mark to avoid infinite recursion on
11748 * circular references not yet examined.
11749 */
11750 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
11751 marked = 1;
11752 }
11753 if (gr->subtypes->subtypes != NULL)
11754 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
11755 gr->subtypes->subtypes);
11756 /*
11757 * Unmark the visited model group definition.
11758 */
11759 if (marked)
11760 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
11761 if (circ != NULL)
11762 return (circ);
11763 } else {
11764 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
11765 (xmlSchemaTypePtr) gr->subtypes);
11766 if (circ != NULL)
11767 return (circ);
11768 }
11769
11770 }
11771 gr = gr->next;
11772 }
11773 return (NULL);
11774}
11775
11776/**
11777 * xmlSchemaCheckGroupDefCircular:
11778 * attrGr: the model group definition
11779 * @ctxt: the parser context
11780 * @name: the name
11781 *
11782 * Checks for circular references to model group definitions.
11783 */
11784static void
11785xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
11786 xmlSchemaParserCtxtPtr ctxt,
11787 const xmlChar * name ATTRIBUTE_UNUSED)
11788{
11789 /*
11790 * Schema Component Constraint: Model Group Correct
11791 * 2 Circular groups are disallowed. That is, within the {particles}
11792 * of a group there must not be at any depth a particle whose {term}
11793 * is the group itself.
11794 */
11795 /*
11796 * NOTE: "gr->subtypes" holds the referenced group.
11797 */
11798 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
11799 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
11800 (modelGrDef->subtypes == NULL))
11801 return;
11802 else {
11803 xmlSchemaTypePtr circ;
11804
11805 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
11806 if (circ != NULL) {
11807 /*
11808 * TODO: Report the referenced attr group as QName.
11809 */
11810 xmlSchemaPCustomErr(ctxt,
11811 XML_SCHEMAP_MG_PROPS_CORRECT_2,
11812 NULL, NULL, circ->node,
11813 "Circular reference to the model group definition '%s' "
11814 "defined", modelGrDef->name);
11815 /*
11816 * NOTE: We will cut the reference to avoid further
11817 * confusion of the processor.
11818 * TODO: SPEC: Does the spec define how to process here?
11819 */
11820 circ->subtypes = NULL;
11821 }
11822 }
11823}
11824
11825
11826/**
11827 * xmlSchemaGetCircAttrGrRef:
11828 * @ctxtGr: the searched attribute group
11829 * @attr: the current attribute list to be processed
11830 *
11831 * This one is intended to be used by
11832 * xmlSchemaCheckSRCAttributeGroupCircular only.
11833 *
11834 * Returns the circular attribute grou reference, otherwise NULL.
11835 */
11836static xmlSchemaAttributeGroupPtr
11837xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
11838 xmlSchemaAttributePtr attr)
11839{
11840 xmlSchemaAttributeGroupPtr circ = NULL, gr;
11841 int marked;
11842 /*
11843 * We will search for an attribute group reference which
11844 * references the context attribute group.
11845 */
11846 while (attr != NULL) {
11847 marked = 0;
11848 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11849 gr = (xmlSchemaAttributeGroupPtr) attr;
11850 if (gr->refItem != NULL) {
11851 if (gr->refItem == ctxtGr)
11852 return (gr);
11853 else if (gr->refItem->flags &
11854 XML_SCHEMAS_ATTRGROUP_MARKED) {
11855 attr = attr->next;
11856 continue;
11857 } else {
11858 /*
11859 * Mark as visited to avoid infinite recursion on
11860 * circular references not yet examined.
11861 */
11862 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
11863 marked = 1;
11864 }
11865 }
11866 if (gr->attributes != NULL)
11867 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
11868 /*
11869 * Unmark the visited group's attributes.
11870 */
11871 if (marked)
11872 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
11873 if (circ != NULL)
11874 return (circ);
11875 }
11876 attr = attr->next;
11877 }
11878 return (NULL);
11879}
11880
11881/**
11882 * xmlSchemaCheckSRCAttributeGroupCircular:
11883 * attrGr: the attribute group definition
11884 * @ctxt: the parser context
11885 * @name: the name
11886 *
11887 * Checks for circular references of attribute groups.
11888 */
11889static void
11890xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
11891 xmlSchemaParserCtxtPtr ctxt,
11892 const xmlChar * name ATTRIBUTE_UNUSED)
11893{
11894 /*
11895 * Schema Representation Constraint:
11896 * Attribute Group Definition Representation OK
11897 * 3 Circular group reference is disallowed outside <redefine>.
11898 * That is, unless this element information item's parent is
11899 * <redefine>, then among the [children], if any, there must
11900 * not be an <attributeGroup> with ref [attribute] which resolves
11901 * to the component corresponding to this <attributeGroup>. Indirect
11902 * circularity is also ruled out. That is, when QName resolution
11903 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
11904 * any <attributeGroup>s with a ref [attribute] among the [children],
11905 * it must not be the case that a ·QName· is encountered at any depth
11906 * which resolves to the component corresponding to this <attributeGroup>.
11907 */
11908 /*
11909 * Only global components can be referenced.
11910 */
11911 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
11912 (attrGr->attributes == NULL))
11913 return;
11914 else {
11915 xmlSchemaAttributeGroupPtr circ;
11916
11917 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
11918 if (circ != NULL) {
11919 /*
11920 * TODO: Report the referenced attr group as QName.
11921 */
11922 xmlSchemaPCustomErr(ctxt,
11923 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
11924 NULL, NULL, circ->node,
11925 "Circular reference to the attribute group '%s' "
11926 "defined", attrGr->name);
11927 /*
11928 * NOTE: We will cut the reference to avoid further
11929 * confusion of the processor.
11930 * BADSPEC: The spec should define how to process in this case.
11931 */
11932 circ->attributes = NULL;
11933 circ->refItem = NULL;
11934 }
11935 }
11936}
11937
11938/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000011939 * xmlSchemaAttrGrpFixup:
11940 * @attrgrpDecl: the schema attribute definition
11941 * @ctxt: the schema parser context
11942 * @name: the attribute name
11943 *
11944 * Fixes finish doing the computations on the attributes definitions
11945 */
11946static void
Daniel Veillard3646d642004-06-02 19:19:14 +000011947xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011948 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000011949{
11950 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011951 name = attrgrp->name;
11952 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011953 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000011954 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011955 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000011956
Daniel Veillardc0826a72004-08-10 14:17:33 +000011957 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
11958 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011959 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011960 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011961 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011962 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
11963 "ref", attrgrp->ref, attrgrp->refNs,
11964 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011965 return;
11966 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011967 attrgrp->refItem = ref;
11968 /*
11969 * Check for self reference!
11970 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011971 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011972 attrgrp->attributes = ref->attributes;
11973 attrgrp->attributeWildcard = ref->attributeWildcard;
11974 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000011975}
11976
11977/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011978 * xmlSchemaAttrFixup:
11979 * @attrDecl: the schema attribute definition
11980 * @ctxt: the schema parser context
11981 * @name: the attribute name
11982 *
11983 * Fixes finish doing the computations on the attributes definitions
11984 */
11985static void
11986xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011987 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011988{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011989 /*
11990 * TODO: If including this is done twice (!) for every attribute.
11991 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011992 /*
11993 * The simple type definition corresponding to the <simpleType> element
11994 * information item in the [children], if present, otherwise the simple
11995 * type definition ·resolved· to by the ·actual value· of the type
11996 * [attribute], if present, otherwise the ·simple ur-type definition·.
11997 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011998 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
11999 return;
12000 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000012001 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012002 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000012003 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012004 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012005 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012006 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012007
Daniel Veillard01fa6152004-06-29 17:04:39 +000012008 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
12009 attrDecl->typeNs);
12010 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012011 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012012 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012013 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
12014 "type", attrDecl->typeName, attrDecl->typeNs,
12015 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012016 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012017 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012018 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012019 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000012020
Daniel Veillardc0826a72004-08-10 14:17:33 +000012021 /*
12022 * TODO: Evaluate, what errors could occur if the declaration is not
12023 * found. It might be possible that the "typefixup" might crash if
12024 * no ref declaration was found.
12025 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012026 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012027 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012028 xmlSchemaPResCompAttrErr(ctxt,
12029 XML_SCHEMAP_SRC_RESOLVE,
12030 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
12031 "ref", attrDecl->ref, attrDecl->refNs,
12032 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012033 return;
12034 }
12035 xmlSchemaAttrFixup(ref, ctxt, NULL);
12036 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012037 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012038 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000012039 }
12040}
12041
12042/**
12043 * xmlSchemaParse:
12044 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000012045 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000012046 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000012047 * XML Shema struture which can be used to validate instances.
12048 * *WARNING* this interface is highly subject to change
12049 *
12050 * Returns the internal XML Schema structure built from the resource or
12051 * NULL in case of error
12052 */
12053xmlSchemaPtr
12054xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
12055{
12056 xmlSchemaPtr ret = NULL;
12057 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012058 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012059 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012060 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012061
12062 xmlSchemaInitTypes();
12063
Daniel Veillard6045c902002-10-09 21:13:59 +000012064 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000012065 return (NULL);
12066
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012067 nberrors = ctxt->nberrors;
12068 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012069 ctxt->counter = 0;
12070 ctxt->container = NULL;
12071
12072 /*
12073 * First step is to parse the input document into an DOM/Infoset
12074 */
Daniel Veillard6045c902002-10-09 21:13:59 +000012075 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012076 doc = xmlReadFile((const char *) ctxt->URL, NULL,
12077 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012078 if (doc == NULL) {
12079 xmlSchemaPErr(ctxt, NULL,
12080 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012081 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012082 ctxt->URL, NULL);
12083 return (NULL);
12084 }
Daniel Veillard6045c902002-10-09 21:13:59 +000012085 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012086 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
12087 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012088 if (doc == NULL) {
12089 xmlSchemaPErr(ctxt, NULL,
12090 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012091 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012092 NULL, NULL);
12093 return (NULL);
12094 }
12095 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000012096 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000012097 } else if (ctxt->doc != NULL) {
12098 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012099 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000012100 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012101 xmlSchemaPErr(ctxt, NULL,
12102 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012103 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012104 NULL, NULL);
12105 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012106 }
12107
12108 /*
12109 * Then extract the root and Schema parse it
12110 */
12111 root = xmlDocGetRootElement(doc);
12112 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012113 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
12114 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012115 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000012116 if (!preserve) {
12117 xmlFreeDoc(doc);
12118 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012119 return (NULL);
12120 }
12121
12122 /*
12123 * Remove all the blank text nodes
12124 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012125 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000012126
12127 /*
12128 * Then do the parsing for good
12129 */
12130 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000012131 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000012132 if (!preserve) {
12133 xmlFreeDoc(doc);
12134 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012135 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000012136 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012137 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012138 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000012139 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012140 ctxt->ctxtType = NULL;
12141 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012142 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000012143 * Then fixup all attributes declarations
12144 */
12145 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
12146
12147 /*
12148 * Then fixup all attributes group declarations
12149 */
12150 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
12151 ctxt);
12152
12153 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012154 * Check attribute groups for circular references.
12155 */
12156 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
12157 xmlSchemaCheckAttributeGroupCircular, ctxt);
12158
12159 /*
12160 * Then fixup all model group definitions.
12161 */
12162 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
12163
12164 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000012165 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000012166 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012167 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012168
12169 /*
12170 * Then fix references of element declaration; apply constraints.
12171 */
12172 xmlHashScanFull(ret->elemDecl,
12173 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012174
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012175 /*
12176 * Check model groups defnitions for circular references.
12177 */
12178 xmlHashScan(ret->groupDecl, (xmlHashScanner)
12179 xmlSchemaCheckGroupDefCircular, ctxt);
12180
12181
Daniel Veillard4255d502002-04-16 15:50:10 +000012182 /*
12183 * Then build the content model for all elements
12184 */
12185 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012186 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012187
12188 /*
12189 * Then check the defaults part of the type like facets values
12190 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012191 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
12192 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012193
Daniel Veillardc0826a72004-08-10 14:17:33 +000012194
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012195 if (ctxt->nberrors != 0) {
12196 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012197 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012198 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012199 return (ret);
12200}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012201
Daniel Veillard4255d502002-04-16 15:50:10 +000012202/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000012203 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000012204 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000012205 * @err: the error callback
12206 * @warn: the warning callback
12207 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000012208 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000012209 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000012210 */
12211void
12212xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012213 xmlSchemaValidityErrorFunc err,
12214 xmlSchemaValidityWarningFunc warn, void *ctx)
12215{
Daniel Veillard4255d502002-04-16 15:50:10 +000012216 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012217 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012218 ctxt->error = err;
12219 ctxt->warning = warn;
12220 ctxt->userData = ctx;
12221}
12222
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012223/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000012224 * xmlSchemaGetParserErrors:
12225 * @ctxt: a XMl-Schema parser context
12226 * @err: the error callback result
12227 * @warn: the warning callback result
12228 * @ctx: contextual data for the callbacks result
12229 *
12230 * Get the callback information used to handle errors for a parser context
12231 *
12232 * Returns -1 in case of failure, 0 otherwise
12233 */
12234int
12235xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
12236 xmlSchemaValidityErrorFunc * err,
12237 xmlSchemaValidityWarningFunc * warn, void **ctx)
12238{
12239 if (ctxt == NULL)
12240 return(-1);
12241 if (err != NULL)
12242 *err = ctxt->error;
12243 if (warn != NULL)
12244 *warn = ctxt->warning;
12245 if (ctx != NULL)
12246 *ctx = ctxt->userData;
12247 return(0);
12248}
12249
12250/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012251 * xmlSchemaFacetTypeToString:
12252 * @type: the facet type
12253 *
12254 * Convert the xmlSchemaTypeType to a char string.
12255 *
12256 * Returns the char string representation of the facet type if the
12257 * type is a facet and an "Internal Error" string otherwise.
12258 */
12259static const char *
12260xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
12261{
12262 switch (type) {
12263 case XML_SCHEMA_FACET_PATTERN:
12264 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012265 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012266 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012268 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012269 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012270 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012271 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012272 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012273 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012274 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012275 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012276 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012277 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012278 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012279 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012280 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012281 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012282 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012283 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012284 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012285 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012286 return ("fractionDigits");
12287 default:
12288 break;
12289 }
12290 return ("Internal Error");
12291}
12292
Daniel Veillardc0826a72004-08-10 14:17:33 +000012293static xmlChar *
12294xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
12295 const xmlChar *cur = value;
12296 xmlChar *ret = NULL, *mcur;
12297
12298 if (value == NULL)
12299 return(NULL);
12300
12301 while ((*cur != 0) &&
12302 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
12303 cur++;
12304 }
12305 if (*cur == 0)
12306 return (NULL);
12307 ret = xmlStrdup(value);
12308 /* TODO FIXME: I guess gcc will bark at this. */
12309 mcur = (xmlChar *) (ret + (cur - value));
12310 do {
12311 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
12312 *mcur = ' ';
12313 mcur++;
12314 } while (*mcur != 0);
12315 return(ret);
12316}
12317
12318static int
12319xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
12320{
12321 xmlSchemaTypePtr anc;
12322
12323 /*
12324 * The normalization type can be changed only for types which are derived
12325 * from xsd:string.
12326 */
12327 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12328 if ((type->builtInType == XML_SCHEMAS_STRING) &&
12329 (type->builtInType == XML_SCHEMAS_NORMSTRING))
12330
12331 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12332 else {
12333 /*
12334 * For all ·atomic· datatypes other than string (and types ·derived·
12335 * by ·restriction· from it) the value of whiteSpace is fixed to
12336 * collapse
12337 */
12338 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12339 }
12340 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12341 /*
12342 * For list types the facet "whiteSpace" is fixed to "collapse".
12343 */
12344 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12345 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12346 return (-1);
12347 } else if (type->facetSet != NULL) {
12348 xmlSchemaTypePtr anyST;
12349 xmlSchemaFacetLinkPtr lin;
12350
12351 /*
12352 * Atomic types.
12353 */
12354 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12355 anc = type->baseType;
12356 do {
12357 /*
12358 * For all ·atomic· datatypes other than string (and types ·derived·
12359 * by ·restriction· from it) the value of whiteSpace is fixed to
12360 * collapse
12361 */
12362 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
12363 (anc->builtInType == XML_SCHEMAS_STRING)) {
12364
12365 lin = type->facetSet;
12366 do {
12367 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
12368 if (lin->facet->whitespace ==
12369 XML_SCHEMAS_FACET_COLLAPSE) {
12370 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12371 } else if (lin->facet->whitespace ==
12372 XML_SCHEMAS_FACET_REPLACE) {
12373 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
12374 } else
12375 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12376 break;
12377 }
12378 lin = lin->next;
12379 } while (lin != NULL);
12380 break;
12381 }
12382 anc = anc->baseType;
12383 } while (anc != anyST);
12384 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12385 }
12386 return (-1);
12387}
12388
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012389/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000012390 * xmlSchemaValidateFacetsInternal:
12391 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000012392 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000012393 * @facets: the list of facets to check
12394 * @value: the lexical repr of the value to validate
12395 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000012396 * @fireErrors: if 0, only internal errors will be fired;
12397 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000012398 *
12399 * Check a value against all facet conditions
12400 *
12401 * Returns 0 if the element is schemas valid, a positive error code
12402 * number otherwise and -1 in case of internal or API error.
12403 */
12404static int
12405xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012406 xmlSchemaTypePtr type,
12407 const xmlChar * value,
12408 unsigned long length,
12409 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012410{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012411 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012412 xmlSchemaTypePtr biType; /* The build-in type. */
12413 xmlSchemaTypePtr tmpType;
12414 xmlSchemaFacetLinkPtr facetLink;
12415 int retFacet, hasFacet;
12416 xmlSchemaFacetPtr facet;
12417 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012418
Daniel Veillardc0826a72004-08-10 14:17:33 +000012419#ifdef DEBUG_UNION_VALIDATION
12420 printf("Facets of type: '%s'\n", (const char *) type->name);
12421 printf(" fireErrors: %d\n", fireErrors);
12422#endif
12423
12424 /*
12425 * NOTE: Do not jump away, if the facetSet of the given type is
12426 * empty: until now, "pattern" facets of the *base types* need to
12427 * be checked as well.
12428 */
12429 biType = type->baseType;
12430 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12431 biType = biType->baseType;
12432 if (biType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012433 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012434 "Internal error: xmlSchemaValidateFacetsInternal, "
12435 "the base type axis of the given type '%s' does not resolve to "
12436 "a built-in type.\n",
12437 type->name, NULL);
12438 return (-1);
12439 }
12440
12441 if (type->facetSet != NULL) {
12442 facetLink = type->facetSet;
12443 while (facetLink != NULL) {
12444 facet = facetLink->facet;
12445 /*
12446 * Skip the pattern "whiteSpace": it is used to
12447 * format the character content beforehand.
12448 */
12449 switch (facet->type) {
12450 case XML_SCHEMA_FACET_WHITESPACE:
12451 case XML_SCHEMA_FACET_PATTERN:
12452 case XML_SCHEMA_FACET_ENUMERATION:
12453 break;
12454 case XML_SCHEMA_FACET_LENGTH:
12455 case XML_SCHEMA_FACET_MINLENGTH:
12456 case XML_SCHEMA_FACET_MAXLENGTH:
12457 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12458 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12459 value, length, 0);
12460 len = length;
12461 } else
12462 ret = xmlSchemaValidateLengthFacet(biType, facet,
12463 value, ctxt->value, &len);
12464 break;
12465 default:
12466 ret = xmlSchemaValidateFacet(biType, facet, value,
12467 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012468 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012469 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012470 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012471 "Internal error: xmlSchemaValidateFacetsInternal, "
12472 "validating facet of type '%s'.\n",
12473 type->name, NULL);
12474 break;
12475 } else if ((ret > 0) && (fireErrors)) {
12476 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, len,
12477 type, facet, NULL, NULL, NULL, NULL);
12478 }
12479
12480 facetLink = facetLink->next;
12481 }
12482 if (ret >= 0) {
12483 /*
12484 * Process enumerations.
12485 */
12486 retFacet = 0;
12487 facetLink = type->facetSet;
12488 while (facetLink != NULL) {
12489 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12490 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12491 value, ctxt->value);
12492 if (retFacet <= 0)
12493 break;
12494 }
12495 facetLink = facetLink->next;
12496 }
12497 if (retFacet > 0) {
12498 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12499 if (fireErrors)
12500 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur,
12501 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12502 } else if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012503 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012504 "Internal error: xmlSchemaValidateFacetsInternal, "
12505 "validating facet of type '%s'.\n",
12506 BAD_CAST "enumeration", NULL);
12507 ret = -1;
12508 }
12509 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012510 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012511 if (ret >= 0) {
12512 /*
12513 * Process patters. Pattern facets are ORed at type level
12514 * and ANDed if derived. Walk the base type axis.
12515 */
12516 hasFacet = 0;
12517 tmpType = type;
12518 facet = NULL;
12519 do {
12520 retFacet = 0;
12521 for (facetLink = tmpType->facetSet; facetLink != NULL;
12522 facetLink = facetLink->next) {
12523 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
12524 continue;
12525 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12526 value, ctxt->value);
12527 if (retFacet <= 0)
12528 break;
12529 else
12530 /* Save the last non-validating facet. */
12531 facet = facetLink->facet;
12532 }
12533 if (retFacet != 0)
12534 break;
12535 tmpType = tmpType->baseType;
12536 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
12537 if (retFacet < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012538 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012539 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12540 "validating 'pattern' facets of type '%s'.\n",
12541 tmpType->name, NULL);
12542 ret = -1;
12543 } else if (retFacet > 0) {
12544 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
12545 if (fireErrors) {
12546 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, 0, type, facet,
12547 NULL, NULL, NULL, NULL);
12548 }
12549 }
12550 }
12551
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012552 return (ret);
12553}
12554
Daniel Veillard4255d502002-04-16 15:50:10 +000012555/************************************************************************
12556 * *
12557 * Simple type validation *
12558 * *
12559 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000012560
Daniel Veillard4255d502002-04-16 15:50:10 +000012561
12562/************************************************************************
12563 * *
12564 * DOM Validation code *
12565 * *
12566 ************************************************************************/
12567
12568static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012569 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012570static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012571 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000012572 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012573static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012574 xmlNodePtr elem,
12575 xmlSchemaElementPtr elemDecl,
12576 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012577
Daniel Veillard3646d642004-06-02 19:19:14 +000012578
12579/**
12580 * xmlSchemaFreeAttrStates:
12581 * @state: a list of attribute states
12582 *
12583 * Free the given list of attribute states
12584 *
12585 */
12586static void
12587xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
12588{
12589 xmlSchemaAttrStatePtr tmp;
12590 while (state != NULL) {
12591 tmp = state;
12592 state = state->next;
12593 xmlFree(tmp);
12594 }
12595}
12596
Daniel Veillard4255d502002-04-16 15:50:10 +000012597/**
12598 * xmlSchemaRegisterAttributes:
12599 * @ctxt: a schema validation context
12600 * @attrs: a list of attributes
12601 *
12602 * Register the list of attributes as the set to be validated on that element
12603 *
12604 * Returns -1 in case of error, 0 otherwise
12605 */
12606static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012607xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
12608{
Daniel Veillard3646d642004-06-02 19:19:14 +000012609 xmlSchemaAttrStatePtr tmp;
12610
12611 ctxt->attr = NULL;
12612 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012613 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012614 if ((attrs->ns != NULL) &&
12615 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
12616 attrs = attrs->next;
12617 continue;
12618 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012619 tmp = (xmlSchemaAttrStatePtr)
12620 xmlMalloc(sizeof(xmlSchemaAttrState));
12621 if (tmp == NULL) {
12622 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
12623 return (-1);
12624 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012625 tmp->attr = attrs;
12626 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
12627 tmp->next = NULL;
12628 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012629 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012630 else
12631 ctxt->attrTop->next = tmp;
12632 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012633 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012634 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012635 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012636}
12637
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012638#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000012639/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012640 * xmlSchemaValidateCheckNodeList
12641 * @nodelist: the list of nodes
12642 *
12643 * Check the node list is only made of text nodes and entities pointing
12644 * to text nodes
12645 *
12646 * Returns 1 if true, 0 if false and -1 in case of error
12647 */
12648static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012649xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
12650{
Daniel Veillard4255d502002-04-16 15:50:10 +000012651 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012652 if (nodelist->type == XML_ENTITY_REF_NODE) {
12653 TODO /* implement recursion in the entity content */
12654 }
12655 if ((nodelist->type != XML_TEXT_NODE) &&
12656 (nodelist->type != XML_COMMENT_NODE) &&
12657 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000012658 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012659 return (0);
12660 }
12661 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012662 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012663 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012664}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012665#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012666
12667/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012668 * xmlSchemaValidateCallback:
12669 * @ctxt: a schema validation context
12670 * @name: the name of the element detected (might be NULL)
12671 * @type: the type
12672 *
12673 * A transition has been made in the automata associated to an element
12674 * content model
12675 */
12676static void
12677xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012678 const xmlChar * name ATTRIBUTE_UNUSED,
12679 xmlSchemaTypePtr type, xmlNodePtr node)
12680{
Daniel Veillard4255d502002-04-16 15:50:10 +000012681 xmlSchemaTypePtr oldtype = ctxt->type;
12682 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012683
Daniel Veillard4255d502002-04-16 15:50:10 +000012684#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000012685 xmlGenericError(xmlGenericErrorContext,
12686 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012687 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012688#endif
12689 ctxt->type = type;
12690 ctxt->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012691 xmlSchemaValidateContent(ctxt, node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012692 ctxt->type = oldtype;
12693 ctxt->node = oldnode;
12694}
12695
Daniel Veillard01fa6152004-06-29 17:04:39 +000012696/**
12697 * xmlSchemaValidateSimpleTypeValue:
12698 * @ctxt: a schema validation context
12699 * @value: the value to be validated
12700 * @fireErrors: shall errors be reported?
12701 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000012702 * @normalize: shall the value be normalized?
Daniel Veillard01fa6152004-06-29 17:04:39 +000012703 *
12704 * Validates a value by the given type (user derived or built-in).
12705 *
12706 * Returns 0 if the value is valid, a positive error code
12707 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012708 */
12709static int
12710xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
12711 const xmlChar *value,
12712 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012713 int applyFacets,
12714 int normalize)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012715{
12716 xmlSchemaTypePtr type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012717 int ret = 0;
12718 xmlChar *normValue = NULL;
12719 int wtsp;
12720
12721 type = ctxt->type;
12722 wtsp = ctxt->valueWS;
12723 /*
12724 * Normalize the value.
12725 */
12726 if (normalize &&
12727 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
12728 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
12729
12730 if ((norm != -1) && (norm > ctxt->valueWS)) {
12731 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12732 normValue = xmlSchemaCollapseString(value);
12733 else
12734 normValue = xmlSchemaWhiteSpaceReplace(value);
12735 ctxt->valueWS = norm;
12736 if (normValue != NULL)
12737 value = (const xmlChar *) normValue;
12738 }
12739 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012740 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
12741 xmlSchemaTypePtr base, anyType;
12742
12743 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12744
12745 base = type->baseType;
12746 while ((base != NULL) &&
12747 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
12748 (base->type != XML_SCHEMA_TYPE_BASIC) &&
12749 (base != anyType)) {
12750 base = base->baseType;
12751 }
12752 ctxt->type = base;
12753 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 0, 1);
12754 ctxt->type = type;
12755 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012756 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012757 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12758 "validating complex type '%s'\n",
12759 type->name, NULL);
12760 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12761 /*
12762 * Check facets.
12763 */
12764 /*
12765 * This is somehow not nice, since if an error occurs
12766 * the reported type will be the complex type; the spec
12767 * wants a simple type to be created on the complex type
12768 * if it has a simple content. For now we have to live with
12769 * it.
12770 */
12771 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12772 value, 0, fireErrors);
12773 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012774 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012775 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12776 "validating facets of complex type '%s'\n",
12777 type->name, NULL);
12778 } else if (ret > 0) {
12779 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
12780 /*
12781 Disabled, since the facet validation already reports errors.
12782 if (fireErrors)
12783 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12784 */
12785 }
12786 }
12787 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012788 xmlNodePtr child;
12789
12790 if (ctxt->value != NULL) {
12791 xmlSchemaFreeValue(ctxt->value);
12792 ctxt->value = NULL;
12793 }
12794 child = ctxt->node;
12795 while (child != NULL) {
12796 switch (child->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012797 case XML_TEXT_NODE:
12798 case XML_CDATA_SECTION_NODE:
12799 case XML_PI_NODE:
12800 case XML_COMMENT_NODE:
12801 case XML_XINCLUDE_START:
12802 case XML_XINCLUDE_END:
12803 break;
12804 case XML_ENTITY_REF_NODE:
12805 case XML_ENTITY_NODE:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012806 /* TODO: Scour the entities for illegal nodes. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012807 TODO break;
12808 case XML_ELEMENT_NODE: {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012809 /* NOTE: Changed to an internal error, since the
12810 * existence of an element node will be already checked in
12811 * xmlSchemaValidateSimpleTypeElement and in
12812 * xmlSchemaValidateComplexType.
12813 */
12814 xmlSchemaVCustomErr(ctxt,
12815 XML_SCHEMAV_INTERNAL,
12816 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12817 ctxt->cur, type,
12818 "Element found in content", NULL);
12819 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012820 }
12821 case XML_ATTRIBUTE_NODE:
12822 case XML_DOCUMENT_NODE:
12823 case XML_DOCUMENT_TYPE_NODE:
12824 case XML_DOCUMENT_FRAG_NODE:
12825 case XML_NOTATION_NODE:
12826 case XML_HTML_DOCUMENT_NODE:
12827 case XML_DTD_NODE:
12828 case XML_ELEMENT_DECL:
12829 case XML_ATTRIBUTE_DECL:
12830 case XML_ENTITY_DECL:
12831 case XML_NAMESPACE_DECL:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012832#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardc0826a72004-08-10 14:17:33 +000012833 case XML_DOCB_DOCUMENT_NODE:
12834#endif
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012835 {
12836 xmlSchemaVCustomErr(ctxt,
12837 XML_SCHEMAV_INTERNAL,
12838 /* XML_SCHEMAS_ERR_INVALIDELEM, */
12839 ctxt->cur, NULL,
12840 "Node of unexpected type found in content",
12841 NULL);
12842 return (XML_SCHEMAV_INTERNAL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012843 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012844 }
12845 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012846
12847 }
12848 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), ctxt->cur);
12849 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012850 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
12851 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
12852 else
12853 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012854 if (fireErrors)
12855 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012856 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012857 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012858 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012859 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012860 }
12861 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12862 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
12863 * a literal in the ·lexical space· of {base type definition}
12864 */
12865 ctxt->type = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012866 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0, 0);
12867 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012868 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012869 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012870 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012871 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012872 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012873 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012874 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012875 if (fireErrors)
12876 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12877 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012878 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012879 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012880 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012881 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12882 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012883 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012884 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012885 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012886 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012887 type->name, NULL);
12888 } else if (ret > 0) {
12889 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012890 /*
12891 Disabled, since the facet validation already reports errors.
12892 if (fireErrors)
12893 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12894 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012895 }
12896 }
12897 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12898
12899 xmlSchemaTypePtr tmpType;
12900 const xmlChar *cur, *end;
12901 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012902 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012903
12904 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
12905 * of white space separated tokens, each of which ·match·es a literal
12906 * in the ·lexical space· of {item type definition}
12907 */
12908
Daniel Veillardc0826a72004-08-10 14:17:33 +000012909 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012910 cur = value;
12911 do {
12912 while (IS_BLANK_CH(*cur))
12913 cur++;
12914 end = cur;
12915 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
12916 end++;
12917 if (end == cur)
12918 break;
12919 tmp = xmlStrndup(cur, end - cur);
12920 len++;
12921 ctxt->type = tmpType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012922 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1, 0);
12923 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012924 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012925 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012926 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012927 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12928 "validating an item of list simple type '%s'\n",
12929 type->name, NULL);
12930 break;
12931 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012932 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012933 if (fireErrors)
12934 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012935 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012936 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012937 cur = end;
12938 } while (*cur != 0);
12939 /*
12940 * Check facets.
12941 */
12942 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012943 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012944 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012945 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012946 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012947 } else if ((ret == 0) && (applyFacets)) {
12948 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12949 value, len, fireErrors);
12950 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012951 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012952 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12953 "validating facets of list simple type '%s'\n",
12954 type->name, NULL);
12955 } else if (ret > 0) {
12956 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012957 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012958 Disabled, since the facet validation already reports errors.
12959 if (fireErrors)
12960 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012961 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012962 }
12963
Daniel Veillard01fa6152004-06-29 17:04:39 +000012964 }
12965 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12966 xmlSchemaTypeLinkPtr memberLink;
12967
12968 /*
12969 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
12970 * not apply directly; however, the normalization behavior of ·union·
12971 * types is controlled by the value of whiteSpace on that one of the
12972 * ·memberTypes· against which the ·union· is successfully validated.
12973 *
12974 * This means that the value is normalized by the first validating
12975 * member type, then the facets of the union type are applied. This
12976 * needs changing of the value!
12977 */
12978
12979 /*
12980 * 1.2.3 if {variety} is ·union· then the string must ·match· a
12981 * literal in the ·lexical space· of at least one member of
12982 * {member type definitions}
12983 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012984#ifdef DEBUG_UNION_VALIDATION
12985 printf("Union ST : '%s'\n", (const char *) type->name);
12986 printf(" fireErrors : %d\n", fireErrors);
12987 printf(" applyFacets: %d\n", applyFacets);
12988#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000012989 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
12990 if (memberLink == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012991 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012992 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012993 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012994 type->name, NULL);
12995 ret = -1;
12996 }
12997 if (ret == 0) {
12998 while (memberLink != NULL) {
12999 ctxt->type = memberLink->type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013000 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013001 if ((ret <= 0) || (ret == 0))
13002 break;
13003 memberLink = memberLink->next;
13004 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013005 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013006 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013007 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013008 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013009 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013010 type->name, NULL);
13011 } else if (ret > 0) {
13012 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013013 if (fireErrors)
13014 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13015 }
13016 }
13017 /*
13018 * Apply facets (pattern, enumeration).
13019 */
13020 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
13021 int mws;
13022 /*
13023 * The normalization behavior of ·union· types is controlled by
13024 * the value of whiteSpace on that one of the ·memberTypes·
13025 * against which the ·union· is successfully validated.
13026 */
13027 if (normValue != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013028 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013029 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13030 "the value was already normalized for the union simple "
13031 "type '%s'.\n", type->name, NULL);
13032 }
13033 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
13034 if (mws > ctxt->valueWS) {
13035 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
13036 normValue = xmlSchemaCollapseString(value);
13037 else
13038 normValue = xmlSchemaWhiteSpaceReplace(value);
13039 if (normValue != NULL)
13040 value = (const xmlChar *) normValue;
13041 }
13042
13043 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13044 value, 0, fireErrors);
13045 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013046 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013047 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13048 "validating facets of union simple type '%s'\n",
13049 type->name, NULL);
13050 } else if (ret > 0) {
13051 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
13052 /*
13053 if (fireErrors)
13054 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13055 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013056 }
13057 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013058 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059 ctxt->type = type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013060 ctxt->valueWS = wtsp;
13061 if (normValue != NULL)
13062 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013063 return (ret);
13064}
13065
13066/**
13067 * xmlSchemaValidateSimpleTypeElement:
13068 * @ctxt: a schema validation context
13069 * @node: the element node to be validated.
13070 *
13071 * Validate the element against a simple type.
13072 *
13073 * Returns 0 if the element is valid, a positive error code
13074 * number otherwise and -1 in case of an internal or API error.
13075 */
13076static int
13077xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13078{
13079 xmlNodePtr child;
13080 xmlSchemaTypePtr type;
13081 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013082 int ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013083 xmlChar *value;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013084 xmlNodePtr cur;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013085
13086
13087 child = ctxt->node;
13088 type = ctxt->type;
13089
13090 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013091 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013092 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
13093 node->name, NULL);
13094 return (-1);
13095 }
13096
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013097 /*
13098 * cvc-type: 3.1.2 The element information item must have no element
13099 * information item [children].
13100 */
13101 cur = child;
13102 while (cur != NULL) {
13103 if (cur->type == XML_ELEMENT_NODE) {
13104 xmlSchemaVCustomErr(ctxt,
13105 XML_SCHEMAV_CVC_TYPE_3_1_2,
13106 node, type,
13107 "No element content allowed", NULL);
13108 return (XML_SCHEMAV_CVC_TYPE_3_1_2);
13109 }
13110 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013111 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013112
Daniel Veillard01fa6152004-06-29 17:04:39 +000013113 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013114 * cvc-type 3.1.1:
13115 *
13116 * The attributes of must be empty, excepting those whose namespace name
13117 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
13118 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
13119 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120 attr = node->properties;
13121 while (attr != NULL) {
13122 if ((attr->ns == NULL) ||
13123 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
13124 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
13125 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
13126 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
13127 (!xmlStrEqual
13128 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013129 xmlSchemaVIllegalAttrErr(ctxt,
13130 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013131 return (ctxt->err);
13132 }
13133 attr = attr->next;
13134 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013135 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
13136 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
13137 value = xmlNodeGetContent(child);
13138 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
13139 if (value != NULL)
13140 xmlFree(value);
13141 ctxt->type = type;
13142 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013143 return (ret);
13144}
Daniel Veillard4255d502002-04-16 15:50:10 +000013145
13146/**
13147 * xmlSchemaValidateElementType:
13148 * @ctxt: a schema validation context
13149 * @node: the top node.
13150 *
13151 * Validate the content of an element type.
13152 * Validation Rule: Element Locally Valid (Complex Type)
13153 *
13154 * Returns 0 if the element is schemas valid, a positive error code
13155 * number otherwise and -1 in case of internal or API error.
13156 */
13157static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013158xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13159{
Daniel Veillard4255d502002-04-16 15:50:10 +000013160 xmlNodePtr child;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013161 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000013162 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000013163 int ret;
13164 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
13165
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000013167 /*
13168 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
13169 * go in here as well.
13170 */
13171
13172 /* TODO: Is this one called always with an element declaration as the
13173 * context's type?
13174 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013175
13176 oldregexp = ctxt->regexp;
13177
13178 child = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013179 decl = (xmlSchemaElementPtr) ctxt->type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013180
Daniel Veillardc0826a72004-08-10 14:17:33 +000013181 if ((ctxt == NULL) || (decl == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013182 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013183 "Internal error: xmlSchemaValidateElementType\n",
13184 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013185 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013186 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013187 /*
13188 * TODO: Since this should be already checked by the content model automaton,
13189 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
13190 * has been changed to XML_SCHEMAV_INTERNAL.
13191 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013192 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013193 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013194 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13195 /* XML_SCHEMAS_ERR_MISSING, */
13196 "Element %s: missing child %s\n",
13197 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013198 }
13199 return (ctxt->err);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013200 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013201
13202 /*
13203 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013204 * TODO, FIXME: Can this still happen here? Isn't this already checked
13205 * by the content model automaton?
13206 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013207 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013208 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
13209 /* XML_SCHEMAS_ERR_WRONGELEM, */
13210 "Element %s: missing child %s found %s\n",
13211 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013212 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013213 }
13214 /*
13215 * Verify the attributes
13216 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013217 /*
13218 * TODO: This "attrTop" thing is not needed any more.
13219 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013220 attrs = ctxt->attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013221 attrTop = ctxt->attrTop;
13222 xmlSchemaRegisterAttributes(ctxt, child->properties);
13223 xmlSchemaValidateAttributes(ctxt, child, decl->subtypes);
13224 if (ctxt->attr != NULL)
13225 xmlSchemaFreeAttributeStates(ctxt->attr);
13226 ctxt->attr = attrs;
13227 ctxt->attrTop = attrTop;
Daniel Veillard3646d642004-06-02 19:19:14 +000013228
Daniel Veillard4255d502002-04-16 15:50:10 +000013229 /*
13230 * Verify the element content recursively
Daniel Veillardc0826a72004-08-10 14:17:33 +000013231 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013232 oldregexp = ctxt->regexp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013233 /*
13234 * FIXME TODO: This one creates a regexp even if no content
13235 * model was defined. Somehow ->contModel is always not NULL
13236 * for complex types, even if they are empty.
13237 */
13238 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013239 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
13240 (xmlRegExecCallbacks)
13241 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013242#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013243 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013244#endif
13245 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013246 xmlSchemaValidateType(ctxt, child, decl, decl->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000013247
13248 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013249 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013250#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013251 xmlGenericError(xmlGenericErrorContext,
13252 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013253#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013254 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013255 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13256 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013257 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013258 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
13259 node, decl->subtypes, "The element content is not valid", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013260#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013261 } else {
13262 xmlGenericError(xmlGenericErrorContext,
13263 "Element %s content check succeeded\n",
13264 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013265
13266#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013267 }
13268 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000013269 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013270 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000013271 ctxt->node = child;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013272 ctxt->type = (xmlSchemaTypePtr) decl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013273 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013274}
13275
Daniel Veillard4255d502002-04-16 15:50:10 +000013276/**
Daniel Veillardc0826a72004-08-10 14:17:33 +000013277 * xmlSchemaValidateAnyInternal:
13278 * @ctxt: a schema validation context
13279 * @node: the top node.
13280 *
13281 * Represents the recursive portion of xmlSchemaValidateAny. Not
13282 * intended to be used by other functions.
13283 *
13284 * Returns 0 if the element is valid, a positive error code
13285 * number otherwise and -1 in case of an internal error.
13286 */
13287static int
13288xmlSchemaValidateAnyInternal(xmlSchemaValidCtxtPtr ctxt,
13289 xmlSchemaWildcardPtr wild,
13290 xmlNodePtr node)
13291{
13292 const xmlChar *uri;
13293 int ret = 0;
13294 xmlNodePtr child;
13295
13296 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
13297 xmlSchemaElementPtr decl = NULL;
13298
13299 if (node->ns != NULL)
13300 decl = xmlHashLookup3(ctxt->schema->elemDecl,
13301 node->name, node->ns->href, NULL);
13302 else
13303 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13304 if (decl != NULL) {
13305 ctxt->node = node;
13306 ctxt->type = (xmlSchemaTypePtr) decl;
13307 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13308 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013309 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013310 "Internal error: xmlSchemaValidateAnyInternal, "
13311 "validating an element in the context of a wildcard.",
13312 NULL, NULL);
13313 } else if (ret > 0)
13314 return (ret);
13315 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
13316 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013317 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
13318 node, wild, "Global declaration is absent");
Daniel Veillardc0826a72004-08-10 14:17:33 +000013319 return (ctxt->err);
13320 }
13321 }
13322 if (node->children != NULL) {
13323 child = node->children;
13324 do {
13325 if (child->type == XML_ELEMENT_NODE) {
13326 if (child->ns != NULL)
13327 uri = child->ns->href;
13328 else
13329 uri = NULL;
13330 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013331 /* TODO: error code. */
13332 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013333 child, wild,
13334 "The namespace of the element is not allowed.");
13335 return (ctxt->err);
13336 }
13337 ret = xmlSchemaValidateAnyInternal(ctxt, wild, child);
13338 if (ret != 0)
13339 return (ret);
13340 }
13341 child = child->next;
13342 } while (child != NULL);
13343 }
13344 return (0);
13345}
13346
13347/**
13348 * xmlSchemaValidateAny:
13349 * @ctxt: a schema validation context
13350 *
13351 * Returns 0 if the element is valid, a positive error code
13352 * number otherwise and -1 in case of an internal or API error.
13353 */
13354static int
13355xmlSchemaValidateAny(xmlSchemaValidCtxtPtr ctxt)
13356{
13357 return(xmlSchemaValidateAnyInternal(ctxt,
13358 ctxt->type->attributeWildcard, ctxt->cur));
13359}
13360
13361/**
William M. Brack2f2a6632004-08-20 23:09:47 +000013362 * xmlSchemaValidateAnyTypeContent:
13363 * @ctxt: a schema validation context
13364 * @node: the current element
13365 *
13366 * This one validates the content of an element of the type
13367 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
13368 * thus elements in the subtree will be validated, if a corresponding
13369 * declaration in the schema exists.
13370 *
13371 * Returns 0 if the element and its subtree is valid, a positive error code
13372 * otherwise and -1 in case of an internal or API error.
13373 */
13374static int
13375xmlSchemaValidateAnyTypeContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13376{
13377 xmlNodePtr top = node;
13378 xmlSchemaTypePtr decl;
13379 int skipContent, ret;
13380
13381 if (node->children == NULL)
13382 return (0);
13383 node = node->children;
13384 while (node != NULL) {
13385 skipContent = 0;
13386 if (node->type == XML_ELEMENT_NODE) {
13387 /*
13388 * The process contents of the wildcard is "lax", thus
13389 * we need to validate the element if a declaration
13390 * exists.
13391 */
13392 if (node->ns != NULL)
13393 decl = xmlHashLookup3(ctxt->schema->elemDecl,
13394 node->name, node->ns->href, NULL);
13395 else
13396 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13397
13398 if (decl != NULL) {
13399 ctxt->node = node;
13400 ctxt->type = (xmlSchemaTypePtr) decl;
13401 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13402 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013403 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013404 "Internal error: xmlSchemaValidateAnyTypeContent, "
13405 "validating an element in the context of a wildcard.",
13406 NULL, NULL);
13407 return (ret);
13408 } else if (ret > 0)
13409 return (ret);
13410 skipContent = 1;
13411 }
13412 }
13413 /*
13414 * Browse the full subtree, deep first.
13415 */
13416 if ((skipContent == 0) && (node->children != NULL)) {
13417 /* deep first */
13418 node = node->children;
13419 } else if ((node != top) && (node->next != NULL)) {
13420 /* then siblings */
13421 node = node->next;
13422 } else if (node != top) {
13423 /* go up to parents->next if needed */
13424 while (node != top) {
13425 if (node->parent != NULL)
13426 node = node->parent;
13427 if ((node != top) && (node->next != NULL)) {
13428 node = node->next;
13429 break;
13430 }
13431 if (node->parent == NULL) {
13432 node = NULL;
13433 break;
13434 }
13435 }
13436 /* exit condition */
13437 if (node == top)
13438 node = NULL;
13439 } else
13440 break;
13441 }
13442 return (0);
13443}
13444
13445/**
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013446 * xmlSchemaHasElemOrCharContent:
13447 * @node: the node
13448 *
13449 * Scours the content of the given node for element
13450 * and character nodes.
13451 *
13452 * Returns 1 if an element or character node is found,
13453 * 0 otherwise.
13454 */
13455static int
13456xmlSchemaHasElemOrCharContent(xmlNodePtr node)
13457{
13458 xmlNodePtr cur;
13459
13460 if (node == NULL)
13461 return (0);
13462 cur = node->children;
13463 while (cur != NULL) {
13464 if ((cur->type == XML_ELEMENT_NODE) ||
13465 /*
13466 * TODO: Ask Daniel if these are all character nodes.
13467 */
13468 (cur->type == XML_TEXT_NODE) ||
13469 (cur->type == XML_CDATA_SECTION_NODE) ||
13470 /*
13471 * TODO: How XML_ENTITY_NODEs evaluated?
13472 */
13473 (cur->type == XML_ENTITY_REF_NODE) ||
13474 (cur->type == XML_ENTITY_NODE)) {
13475 return (1);
13476 }
13477 cur = cur->next;
13478 }
13479 return (0);
13480}
13481
13482/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013483 * xmlSchemaValidateComplexType:
13484 * @ctxt: a schema validation context
13485 * @node: the top node.
13486 *
13487 * Validate the content of an element expected to be a complex type type
13488 * xmlschema-1.html#cvc-complex-type
13489 * Validation Rule: Element Locally Valid (Complex Type)
13490 *
13491 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000013492 * number otherwise and -1 in case of internal or API error.
13493 * Note on reported errors: Although it might be nice to report
13494 * the name of the simple/complex type, used to validate the content
13495 * of a node, it is quite unnecessary: for global defined types
13496 * the local name of the element is equal to the NCName of the type,
13497 * for local defined types it makes no sense to output the internal
13498 * computed name of the type. TODO: Instead, one should attach the
13499 * struct of the type involved to the error handler - this allows
13500 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000013501 */
13502static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013503xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13504{
Daniel Veillard4255d502002-04-16 15:50:10 +000013505 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 xmlSchemaTypePtr type;
13507 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000013508 const xmlChar *nsUri;
Daniel Veillard3646d642004-06-02 19:19:14 +000013509
Daniel Veillard4255d502002-04-16 15:50:10 +000013510 child = ctxt->node;
13511 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013512 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013513
Daniel Veillard4255d502002-04-16 15:50:10 +000013514 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 case XML_SCHEMA_CONTENT_EMPTY: {
13516 /*
13517 * 1 If the {content type} is empty, then the element information
13518 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000013519 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 /*
13521 * TODO: Is the entity stuff correct?
13522 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013523 if (xmlSchemaHasElemOrCharContent(node) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013524 xmlSchemaVComplexTypeErr(ctxt,
13525 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
13526 node, type,
13527 "Character or element content is not allowed, "
13528 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013530 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013531 }
13532 case XML_SCHEMA_CONTENT_ELEMENTS:
13533 case XML_SCHEMA_CONTENT_MIXED:
13534 while (child != NULL) {
13535 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013536 if (child->ns != NULL)
13537 nsUri = child->ns->href;
13538 else
13539 nsUri = NULL;
13540 ret = xmlRegExecPushString2(ctxt->regexp,
13541 child->name, nsUri, child);
13542#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 if (ret < 0)
13544 xmlGenericError(xmlGenericErrorContext,
13545 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000013546 else
13547 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 " --> %s\n", child->name);
13549#endif
13550 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
13551 /*
13552 * TODO: Ask Daniel if this are all character nodes.
13553 */
13554 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
13555 (child->type == XML_ENTITY_NODE) ||
13556 (child->type == XML_ENTITY_REF_NODE) ||
13557 (child->type == XML_CDATA_SECTION_NODE))) {
13558 /*
13559 * 2.3 If the {content type} is element-only, then the
13560 * element information item has no character information
13561 * item [children] other than those whose [character
13562 * code] is defined as a white space in [XML 1.0 (Second
13563 * Edition)].
13564 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013565 xmlSchemaVComplexTypeErr(ctxt,
13566 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
13567 node, type,
13568 "Character content is not allowed, "
13569 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 break;
13571 }
13572 child = child->next;
13573 }
13574 break;
13575 case XML_SCHEMA_CONTENT_SIMPLE:
13576 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 xmlChar *value = NULL;
13578 /*
13579 * We hit a complexType with a simpleContent resolving
13580 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000013581 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013582 /*
13583 * 2.2 If the {content type} is a simple type definition,
13584 * then the element information item has no element
13585 * information item [children], and the ·normalized value·
13586 * of the element information item is ·valid· with respect
13587 * to that simple type definition as defined by String
13588 * Valid (§3.14.4).
13589 */
13590 child = node->children;
13591 while (child != NULL) {
13592 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013593 xmlSchemaVComplexTypeErr(ctxt,
13594 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13595 node, type,
13596 "Element content is not allowed, because "
13597 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013598 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13599 break;
13600 }
13601 child = child->next;
13602 }
13603 if (ret == 0) {
13604 /*
13605 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000013606 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 if (ctxt->node == NULL)
13608 value = NULL;
13609 else
13610 value = xmlNodeGetContent(node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013611 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013612 if (ret > 0) {
13613 /*
13614 * NOTE: Although an error will be reported by
13615 * xmlSchemaValidateSimpleTypeValue, the spec wants
13616 * a specific complex type error to be reported
13617 * additionally.
13618 */
13619 xmlSchemaVComplexTypeErr(ctxt,
13620 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13621 node, type,
13622 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13624 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013625 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013626 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013627 "Element '%s': Error while validating character "
13628 "content against complex type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 node->name, type->name);
13630 return (-1);
13631 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013632 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013633 if (ret == 0) {
13634 /*
13635 * Apply facets of the complexType. Be sure to pass the
13636 * built-in type to xmlSchemaValidateFacetsInternal.
13637 */
13638 /* TODO: I don't know yet if the facets of the simple type
13639 * are used, or if the facets, defined by this complex type,
13640 * are to be used only. This here applies both facet sets.
13641 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013642
13643 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13644 value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013646 xmlSchemaVComplexTypeErr(ctxt,
13647 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13648 node, type,
13649 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013650 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13651 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013652 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013654 "Element '%s': Error while validating character "
13655 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013656 "apply facets.\n",
13657 type->name, NULL);
13658 }
13659 }
13660 if (value != NULL)
13661 xmlFree(value);
13662 /* TODO: facets */
13663 break;
13664 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013665 default:
13666 TODO xmlGenericError(xmlGenericErrorContext,
13667 "unimplemented content type %d\n",
13668 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000013669 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013670 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013671 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013672}
13673
13674/**
13675 * xmlSchemaValidateContent:
13676 * @ctxt: a schema validation context
13677 * @elem: an element
13678 * @type: the type declaration
13679 *
13680 * Validate the content of an element against the type.
13681 *
13682 * Returns 0 if the element is schemas valid, a positive error code
13683 * number otherwise and -1 in case of internal or API error.
13684 */
13685static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013686xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13687{
Daniel Veillard4255d502002-04-16 15:50:10 +000013688 xmlSchemaTypePtr type;
13689
Daniel Veillard4255d502002-04-16 15:50:10 +000013690 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013691 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013692
13693 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013694 case XML_SCHEMA_TYPE_ANY:
Daniel Veillardc0826a72004-08-10 14:17:33 +000013695 xmlSchemaValidateAny(ctxt);
13696 ctxt->type = type;
13697 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013698 case XML_SCHEMA_TYPE_COMPLEX:
13699 xmlSchemaValidateComplexType(ctxt, node);
13700 break;
13701 case XML_SCHEMA_TYPE_ELEMENT:{
13702 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
13703
13704 /*
13705 * Handle element reference here
13706 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013707 /*
13708 * TODO: This should be removed, since checks for
13709 * consistence should not be done during validation.
13710 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013711 if (decl->ref != NULL) {
13712 if (decl->refDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013713 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000013714 "Internal error: element reference %s "
13715 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013716 return (-1);
13717 }
13718 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
13719 decl = decl->refDecl;
13720 }
William M. Bracke7091952004-05-11 15:09:58 +000013721 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013722 xmlSchemaValidateElementType(ctxt, node);
13723 ctxt->type = type;
13724 break;
13725 }
13726 case XML_SCHEMA_TYPE_BASIC:
William M. Brack2f2a6632004-08-20 23:09:47 +000013727 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
13728 xmlSchemaValidateAnyTypeContent(ctxt, node);
13729 else
13730 xmlSchemaValidateSimpleTypeElement(ctxt, node);
13731 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 case XML_SCHEMA_TYPE_SIMPLE:
13733 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013734 break;
13735 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013736 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013737 case XML_SCHEMA_TYPE_SEQUENCE:
13738 TODO break;
13739 case XML_SCHEMA_TYPE_CHOICE:
13740 TODO break;
13741 case XML_SCHEMA_TYPE_ALL:
13742 TODO break;
13743 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13744 TODO break;
13745 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13746 TODO break;
13747 case XML_SCHEMA_TYPE_UR:
13748 TODO break;
13749 case XML_SCHEMA_TYPE_RESTRICTION:
13750 /*xmlSchemaValidateRestrictionType(ctxt, node); */
13751 TODO break;
13752 case XML_SCHEMA_TYPE_EXTENSION:
13753 TODO break;
13754 case XML_SCHEMA_TYPE_ATTRIBUTE:
13755 TODO break;
13756 case XML_SCHEMA_TYPE_GROUP:
13757 TODO break;
13758 case XML_SCHEMA_TYPE_NOTATION:
13759 TODO break;
13760 case XML_SCHEMA_TYPE_LIST:
13761 TODO break;
13762 case XML_SCHEMA_TYPE_UNION:
13763 TODO break;
13764 case XML_SCHEMA_FACET_MININCLUSIVE:
13765 TODO break;
13766 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13767 TODO break;
13768 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13769 TODO break;
13770 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13771 TODO break;
13772 case XML_SCHEMA_FACET_TOTALDIGITS:
13773 TODO break;
13774 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13775 TODO break;
13776 case XML_SCHEMA_FACET_PATTERN:
13777 TODO break;
13778 case XML_SCHEMA_FACET_ENUMERATION:
13779 TODO break;
13780 case XML_SCHEMA_FACET_WHITESPACE:
13781 TODO break;
13782 case XML_SCHEMA_FACET_LENGTH:
13783 TODO break;
13784 case XML_SCHEMA_FACET_MAXLENGTH:
13785 TODO break;
13786 case XML_SCHEMA_FACET_MINLENGTH:
13787 TODO break;
13788 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13789 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000013790 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
13791 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000013792 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013793
13794 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013795 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013796 ctxt->node = ctxt->node->next;
13797 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013798 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013799}
13800
13801/**
13802 * xmlSchemaValidateType:
13803 * @ctxt: a schema validation context
13804 * @elem: an element
13805 * @type: the list of type declarations
13806 *
13807 * Validate the content of an element against the types.
13808 *
13809 * Returns 0 if the element is schemas valid, a positive error code
13810 * number otherwise and -1 in case of internal or API error.
13811 */
13812static int
13813xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013814 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
13815{
Daniel Veillard4255d502002-04-16 15:50:10 +000013816 xmlChar *nil;
13817
Daniel Veillard2db8c122003-07-08 12:16:59 +000013818 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013819 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000013820
Daniel Veillard3646d642004-06-02 19:19:14 +000013821 /* This one is called by "xmlSchemaValidateElementType" and
13822 * "xmlSchemaValidateElement".
13823 */
13824
Daniel Veillard4255d502002-04-16 15:50:10 +000013825 /*
13826 * 3.3.4 : 2
13827 */
13828 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013829 xmlSchemaVCustomErr(ctxt,
13830 XML_SCHEMAV_CVC_ELT_2,
13831 elem, NULL,
13832 "The element declaration is abstract", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013833 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013834 }
13835 /*
13836 * 3.3.4: 3
13837 */
13838 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
13839 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013840 /* 3.3.4: 3.2 */
13841 if (xmlStrEqual(nil, BAD_CAST "true")) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013842 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
13843 xmlSchemaVCustomErr(ctxt,
13844 XML_SCHEMAV_CVC_ELT_3_2_1,
13845 /* XML_SCHEMAS_ERR_NOTEMPTY, */
13846 elem, NULL,
13847 "The 'nilled' element must have no character or element "
13848 "content", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013849 return (ctxt->err);
13850 }
13851 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
13852 (elemDecl->value != NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013853 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
13854 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
13855 elem, NULL,
13856 "There is a fixed value constraint defined for "
13857 "the 'nilled' element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013858 return (ctxt->err);
13859 }
13860 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013861 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013862 /* 3.3.4: 3.1 */
13863 if (nil != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013864 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_1,
13865 /* XML_SCHEMAS_ERR_NOTNILLABLE, */
13866 elem, NULL,
13867 "The element is not 'nillable'", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013868 xmlFree(nil);
13869 return (ctxt->err);
13870 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013871 }
13872
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013873 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000013874
13875 ctxt->type = elemDecl->subtypes;
13876 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013877 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013878 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013879}
13880
13881
13882/**
13883 * xmlSchemaValidateAttributes:
13884 * @ctxt: a schema validation context
13885 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000013886 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000013887 *
13888 * Validate the attributes of an element.
13889 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013890 * 1. Existent, invalid attributes are reported in the form
13891 * "prefix:localName".
13892 * Reason: readability - it is easier to find the actual XML
13893 * representation of the attributes QName.
13894 * 2. Missing attributes are reported in the form
13895 * {"URI", "localName"}.
13896 * This is necessary, since the the prefix need not to be declared
13897 * at all, and thus is not computable.
13898 *
Daniel Veillard4255d502002-04-16 15:50:10 +000013899 * Returns 0 if the element is schemas valid, a positive error code
13900 * number otherwise and -1 in case of internal or API error.
13901 */
13902static int
Daniel Veillard3646d642004-06-02 19:19:14 +000013903xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013904{
Daniel Veillard3646d642004-06-02 19:19:14 +000013905 int ret;
13906 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013907 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013908 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000013909 xmlSchemaAttributeLinkPtr attrUse;
13910 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013911 int found;
William M. Brack803812b2004-06-03 02:11:24 +000013912 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013913#ifdef DEBUG_ATTR_VALIDATION
13914 int redundant = 0;
13915#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013916
Daniel Veillardc0826a72004-08-10 14:17:33 +000013917 /*
13918 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
13919 * if we have an attribute reference or an attribute declaration.
13920 */
13921 /*
13922 * Allow all attributes if the type is anyType.
13923 */
13924 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
13925 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013926 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013927 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013928 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000013929 attrDecl = attrUse->attr;
13930#ifdef DEBUG_ATTR_VALIDATION
13931 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
13932 printf("attr use - use: %d\n", attrDecl->occurs);
13933#endif
13934 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
13935
13936 if (curState->decl == attrUse->attr) {
13937#ifdef DEBUG_ATTR_VALIDATION
13938 redundant = 1;
13939#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013940 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013941 attr = curState->attr;
13942#ifdef DEBUG_ATTR_VALIDATION
13943 printf("attr - name: %s\n", attr->name);
13944 if (attr->ns != NULL)
13945 printf("attr - ns: %s\n", attr->ns->href);
13946 else
13947 printf("attr - ns: none\n");
13948#endif
13949 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013950 if (attr == NULL)
13951 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013952 if (attrDecl->ref != NULL) {
13953 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013954 continue;
13955 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013956 if ((attrDecl->refNs == NULL) ||
13957 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013958 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013959 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013960 continue;
13961 }
13962 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013963 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013964 continue;
13965 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013966 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013967 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013968 if (attr->ns == NULL) {
13969 /*
William M. Bracke7091952004-05-11 15:09:58 +000013970 * accept an unqualified attribute only if the target
13971 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013972 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013973 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000013974 /*
13975 * This check was removed, since the target namespace
13976 * was evaluated during parsing and already took
13977 * "attributeFormDefault" into account.
13978 */
13979 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013980 continue;
13981 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013982 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013983 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013984 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013985 attr->ns->href))
13986 continue;
13987 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013988 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013989#ifdef DEBUG_ATTR_VALIDATION
13990 printf("found\n");
13991#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013992 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000013993 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013994 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013995
Daniel Veillard3646d642004-06-02 19:19:14 +000013996 if (attrDecl->subtypes == NULL) {
13997 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
13998 curState->decl = attrDecl;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013999 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000014000 "Internal error: attribute %s type not resolved\n",
14001 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014002 continue;
14003 }
14004 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014005 ctxt->type = attrDecl->subtypes;
14006 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000014008 if (ret != 0)
14009 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
14010 else
14011 curState->state = XML_SCHEMAS_ATTR_CHECKED;
14012 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014013 if (value != NULL) {
14014 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000014015 }
14016 }
14017 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
14018 xmlSchemaAttrStatePtr tmp;
14019
14020#ifdef DEBUG_ATTR_VALIDATION
14021 printf("required attr not found\n");
14022#endif
14023 /*
14024 * Add a new dummy attribute state.
14025 */
14026 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
14027 if (tmp == NULL) {
14028 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
14029 return (-1);
14030 }
14031 tmp->attr = NULL;
14032 tmp->state = XML_SCHEMAS_ATTR_MISSING;
14033 tmp->decl = attrDecl;
14034 tmp->next = NULL;
14035
14036 if (reqAttrStates == NULL) {
14037 reqAttrStates = tmp;
14038 reqAttrStatesTop = tmp;
14039 } else {
14040 reqAttrStatesTop->next = tmp;
14041 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014042 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014043
14044 }
14045 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014046 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014047 /*
14048 * Add required attributes to the attribute states of the context.
14049 */
14050 if (reqAttrStates != NULL) {
14051 if (ctxt->attr == NULL) {
14052 ctxt->attr = reqAttrStates;
14053 } else {
14054 ctxt->attrTop->next = reqAttrStates;
14055 }
14056 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014057 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014058 /*
14059 * Process wildcards.
14060 */
14061 if (type->attributeWildcard != NULL) {
14062#ifdef DEBUG_ATTR_VALIDATION
14063 xmlSchemaWildcardNsPtr ns;
14064 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014065 if (type->attributeWildcard->processContents ==
14066 XML_SCHEMAS_ANY_LAX)
14067 printf("processContents: lax\n");
14068 else if (type->attributeWildcard->processContents ==
14069 XML_SCHEMAS_ANY_STRICT)
14070 printf("processContents: strict\n");
14071 else
14072 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000014073 if (type->attributeWildcard->any)
14074 printf("type: any\n");
14075 else if (type->attributeWildcard->negNsSet != NULL) {
14076 printf("type: negated\n");
14077 if (type->attributeWildcard->negNsSet->value == NULL)
14078 printf("ns: (absent)\n");
14079 else
14080 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
14081 } else if (type->attributeWildcard->nsSet != NULL) {
14082 printf("type: set\n");
14083 ns = type->attributeWildcard->nsSet;
14084 while (ns != NULL) {
14085 if (ns->value == NULL)
14086 printf("ns: (absent)\n");
14087 else
14088 printf("ns: %s\n", ns->value);
14089 ns = ns->next;
14090 }
14091 } else
14092 printf("empty\n");
14093
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014094
14095#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000014096 curState = ctxt->attr;
14097 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014098 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
14099 if (curState->attr->ns != NULL)
14100 nsURI = curState->attr->ns->href;
14101 else
14102 nsURI = NULL;
14103 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
14104 nsURI)) {
14105 /*
14106 * Handle processContents.
14107 */
14108 if ((type->attributeWildcard->processContents ==
14109 XML_SCHEMAS_ANY_LAX) ||
14110 (type->attributeWildcard->processContents ==
14111 XML_SCHEMAS_ANY_STRICT)) {
14112
14113 attr = curState->attr;
14114 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
14115 attr->name, nsURI);
14116 if (attrDecl != NULL) {
14117 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014118 ctxt->cur = (xmlNodePtr) attr;
14119 ctxt->node = attr->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014120 ctxt->type = attrDecl->subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014121 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014122 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014123 if (ret != 0)
14124 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
14125 else
14126 curState->state = XML_SCHEMAS_ATTR_CHECKED;
14127 curState->decl = attrDecl;
14128 if (value != NULL) {
14129 xmlFree(value);
14130 }
14131
14132 } else if (type->attributeWildcard->processContents ==
14133 XML_SCHEMAS_ANY_LAX) {
14134 curState->state = XML_SCHEMAS_ATTR_CHECKED;
14135 }
14136 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000014137 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014138 }
14139 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014140 curState = curState->next;
14141 }
14142 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014143 /*
14144 * Report missing and illegal attributes.
14145 */
14146 if (ctxt->attr != NULL) {
14147 curState = ctxt->attr;
14148 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
14149 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
14150 attr = curState->attr;
14151 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
14152 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014153 else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
14154 /* TODO: "prohibited" won't ever be touched here!.
14155 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
14156 */
14157 if (type->attributeWildcard == NULL) {
14158 xmlSchemaVIllegalAttrErr(ctxt,
14159 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
14160 } else {
14161 xmlSchemaVIllegalAttrErr(ctxt,
14162 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
14163 }
14164 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014165 }
14166 curState = curState->next;
14167 }
14168 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014169#ifdef DEBUG_ATTR_VALIDATION
14170 if (redundant)
14171 xmlGenericError(xmlGenericErrorContext,
14172 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
14173 type->name);
14174#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014175 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014176}
14177
14178/**
14179 * xmlSchemaValidateElement:
14180 * @ctxt: a schema validation context
14181 * @elem: an element
14182 *
14183 * Validate an element in a tree
14184 *
14185 * Returns 0 if the element is schemas valid, a positive error code
14186 * number otherwise and -1 in case of internal or API error.
14187 */
14188static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014189xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
14190{
Daniel Veillard4255d502002-04-16 15:50:10 +000014191 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000014192 int ret;
14193 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000014194
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014195 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014196 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
14197 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014198 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014199 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
14200 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014201 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014202 /*
14203 * This one is called by xmlSchemaValidateDocument and
14204 * xmlSchemaValidateAnyInernal.
14205 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014206
Daniel Veillard4255d502002-04-16 15:50:10 +000014207 /*
14208 * 3.3.4 : 1
14209 */
14210 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014211 xmlSchemaVCustomErr(ctxt,
14212 XML_SCHEMAV_CVC_ELT_1,
14213 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
14214 elem, NULL,
14215 "Global declaration is absent", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014216 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014217 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014218 /* TODO: This should be already catched at the schema parsing level. */
Daniel Veillard4255d502002-04-16 15:50:10 +000014219 if (elemDecl->subtypes == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014220 xmlSchemaVCustomErr(ctxt,
14221 XML_SCHEMAV_INTERNAL,
14222 /* XML_SCHEMAS_ERR_NOTYPE */
14223 elem, NULL,
14224 "The element declaration has no type assigned", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014225 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014226 }
14227 /*
14228 * Verify the attributes
14229 */
Daniel Veillard3646d642004-06-02 19:19:14 +000014230 attrs = ctxt->attr;
14231 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000014232 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014233 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->subtypes);
14234 if (ctxt->attr != NULL)
14235 xmlSchemaFreeAttributeStates(ctxt->attr);
14236 ctxt->attr = attrs;
14237 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000014238 /*
14239 * Verify the element content recursively
14240 */
14241 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014242 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
14243 (xmlRegExecCallbacks)
14244 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014245#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014246 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014247#endif
14248 }
14249 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014250 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014251 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014252#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014253 xmlGenericError(xmlGenericErrorContext,
14254 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014255#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000014256 if (ret == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014257 /* TODO: error code. */
14258 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14259 elem, elemDecl->subtypes,
14260 "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014261 } else if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014262 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14263 elem, elemDecl->subtypes,
14264 "The element content is not valid", NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014265#ifdef DEBUG_CONTENT
Daniel Veillardc0826a72004-08-10 14:17:33 +000014266 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014267 xmlGenericError(xmlGenericErrorContext,
14268 "Element %s content check succeeded\n",
14269 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014270
14271#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014272 }
14273 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000014274 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014275 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014276}
14277
14278/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000014279 * xmlSchemaValidateOneElement:
14280 * @ctxt: a schema validation context
14281 * @elem: an element node
14282 *
14283 * Validate a branch of a tree, starting with the given @elem.
14284 *
14285 * Returns 0 if the element and its subtree is valid, a positive error
14286 * code number otherwise and -1 in case of an internal or API error.
14287 */
14288int
14289xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
14290{
14291 if ((ctxt == NULL) || (elem == NULL))
14292 return (-1);
14293
14294 ctxt->doc = elem->doc;
14295 ctxt->err = 0;
14296 ctxt->nberrors = 0;
14297 return (xmlSchemaValidateElement(ctxt, elem));
14298}
14299
14300/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014301 * xmlSchemaValidateDocument:
14302 * @ctxt: a schema validation context
14303 * @doc: a parsed document tree
14304 *
14305 * Validate a document tree in memory.
14306 *
14307 * Returns 0 if the document is schemas valid, a positive error code
14308 * number otherwise and -1 in case of internal or API error.
14309 */
14310static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014311xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14312{
Daniel Veillard4255d502002-04-16 15:50:10 +000014313 xmlNodePtr root;
14314 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014315
Daniel Veillard4255d502002-04-16 15:50:10 +000014316 root = xmlDocGetRootElement(doc);
14317 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014318 xmlSchemaVCustomErr(ctxt,
14319 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
14320 (xmlNodePtr) doc, NULL,
14321 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014322 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014323 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014324
Daniel Veillard4255d502002-04-16 15:50:10 +000014325 if (root->ns != NULL)
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014326 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, root->ns->href);
Daniel Veillard4255d502002-04-16 15:50:10 +000014327 else
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014328 elemDecl = xmlSchemaGetElem(ctxt->schema, root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014329 if (elemDecl == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014330 xmlSchemaVCustomErr(ctxt,
14331 XML_SCHEMAV_CVC_ELT_1,
14332 root, NULL,
14333 /* XML_SCHEMAS_ERR_UNDECLAREDELEM, */
14334 "Global declaration is absent", NULL);
14335 }
14336 /*
14337 * Removed, since xmlSchemaGetElem will return global declarations only.
14338 *
14339 else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000014340 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000014341 "Root element %s not global\n", root->name, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014342 }
14343 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014344 /*
14345 * Okay, start the recursive validation
14346 */
14347 xmlSchemaValidateElement(ctxt, root);
14348
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014349 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014350}
14351
14352/************************************************************************
14353 * *
14354 * SAX Validation code *
14355 * *
14356 ************************************************************************/
14357
14358/************************************************************************
14359 * *
14360 * Validation interfaces *
14361 * *
14362 ************************************************************************/
14363
14364/**
14365 * xmlSchemaNewValidCtxt:
14366 * @schema: a precompiled XML Schemas
14367 *
14368 * Create an XML Schemas validation context based on the given schema
14369 *
14370 * Returns the validation context or NULL in case of error
14371 */
14372xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014373xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
14374{
Daniel Veillard4255d502002-04-16 15:50:10 +000014375 xmlSchemaValidCtxtPtr ret;
14376
14377 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
14378 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014379 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014380 return (NULL);
14381 }
14382 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014383 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000014384 ret->attrTop = NULL;
14385 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014386 return (ret);
14387}
14388
14389/**
14390 * xmlSchemaFreeValidCtxt:
14391 * @ctxt: the schema validation context
14392 *
14393 * Free the resources associated to the schema validation context
14394 */
14395void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014396xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
14397{
Daniel Veillard4255d502002-04-16 15:50:10 +000014398 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014399 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014400 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014401 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000014402 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014403 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000014404 xmlFree(ctxt);
14405}
14406
14407/**
14408 * xmlSchemaSetValidErrors:
14409 * @ctxt: a schema validation context
14410 * @err: the error function
14411 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000014412 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000014413 *
William M. Brack2f2a6632004-08-20 23:09:47 +000014414 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000014415 */
14416void
14417xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014418 xmlSchemaValidityErrorFunc err,
14419 xmlSchemaValidityWarningFunc warn, void *ctx)
14420{
Daniel Veillard4255d502002-04-16 15:50:10 +000014421 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014422 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014423 ctxt->error = err;
14424 ctxt->warning = warn;
14425 ctxt->userData = ctx;
14426}
14427
14428/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014429 * xmlSchemaGetValidErrors:
14430 * @ctxt: a XML-Schema validation context
14431 * @err: the error function result
14432 * @warn: the warning function result
14433 * @ctx: the functions context result
14434 *
14435 * Get the error and warning callback informations
14436 *
14437 * Returns -1 in case of error and 0 otherwise
14438 */
14439int
14440xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
14441 xmlSchemaValidityErrorFunc * err,
14442 xmlSchemaValidityWarningFunc * warn, void **ctx)
14443{
14444 if (ctxt == NULL)
14445 return (-1);
14446 if (err != NULL)
14447 *err = ctxt->error;
14448 if (warn != NULL)
14449 *warn = ctxt->warning;
14450 if (ctx != NULL)
14451 *ctx = ctxt->userData;
14452 return (0);
14453}
14454
14455/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014456 * xmlSchemaValidateDoc:
14457 * @ctxt: a schema validation context
14458 * @doc: a parsed document tree
14459 *
14460 * Validate a document tree in memory.
14461 *
14462 * Returns 0 if the document is schemas valid, a positive error code
14463 * number otherwise and -1 in case of internal or API error.
14464 */
14465int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014466xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14467{
Daniel Veillard4255d502002-04-16 15:50:10 +000014468 int ret;
14469
14470 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014471 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014472
14473 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000014474 ctxt->err = 0;
14475 ctxt->nberrors = 0;
14476
Daniel Veillard4255d502002-04-16 15:50:10 +000014477 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014478 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000014479}
14480
14481/**
14482 * xmlSchemaValidateStream:
14483 * @ctxt: a schema validation context
14484 * @input: the input to use for reading the data
14485 * @enc: an optional encoding information
14486 * @sax: a SAX handler for the resulting events
14487 * @user_data: the context to provide to the SAX handler.
14488 *
14489 * Validate a document tree in memory.
14490 *
14491 * Returns 0 if the document is schemas valid, a positive error code
14492 * number otherwise and -1 in case of internal or API error.
14493 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014494int
Daniel Veillard4255d502002-04-16 15:50:10 +000014495xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014496 xmlParserInputBufferPtr input, xmlCharEncoding enc,
14497 xmlSAXHandlerPtr sax, void *user_data)
14498{
Daniel Veillard4255d502002-04-16 15:50:10 +000014499 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014500 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014501 ctxt->input = input;
14502 ctxt->enc = enc;
14503 ctxt->sax = sax;
14504 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014505 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014506}
14507
14508#endif /* LIBXML_SCHEMAS_ENABLED */