blob: 46cb534abb62fde2159f85849456f96ecc1962fa [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++;
374 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
375 }
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 */
409 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000410 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000411 error, XML_ERR_ERROR, NULL, 0,
412 (const char *) str1, (const char *) str2,
413 (const char *) str3, 0, 0,
414 msg, str1, str2, str3);
415}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000416
417/**
418 * xmlSchemaVErrExt:
419 * @ctxt: the validation context
420 * @node: the context node
421 * @error: the error code
422 * @msg: the message
423 * @str1: extra parameter for the message display
424 * @str2: extra parameter for the message display
425 * @str3: extra parameter for the message display
426 * @str4: extra parameter for the message display
427 * @str5: extra parameter for the message display
428 *
429 * Handle a validation error
430 */
431static void
432xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
433 const char *msg, const xmlChar * str1,
434 const xmlChar * str2, const xmlChar * str3,
435 const xmlChar * str4, const xmlChar * str5)
436{
437 xmlStructuredErrorFunc schannel = NULL;
438 xmlGenericErrorFunc channel = NULL;
439 void *data = NULL;
440
441 if (ctxt != NULL) {
442 ctxt->nberrors++;
443 ctxt->err = error;
444 channel = ctxt->error;
445 schannel = ctxt->serror;
446 data = ctxt->userData;
447 }
448 /* reajust to global error numbers */
449 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
450 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
451 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
452 msg, str1, str2, str3, str4, str5);
453}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000454/**
455 * xmlSchemaVErr:
456 * @ctxt: the validation context
457 * @node: the context node
458 * @error: the error code
459 * @msg: the error message
460 * @str1: extra data
461 * @str2: extra data
462 *
463 * Handle a validation error
464 */
465static void
466xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
467 const char *msg, const xmlChar * str1, const xmlChar * str2)
468{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000469 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000470 xmlGenericErrorFunc channel = NULL;
471 void *data = NULL;
472
473 if (ctxt != NULL) {
474 ctxt->nberrors++;
475 ctxt->err = error;
476 channel = ctxt->error;
477 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000478 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000479 }
480 /* reajust to global error numbers */
481 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000482 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000483 error, XML_ERR_ERROR, NULL, 0,
484 (const char *) str1, (const char *) str2, NULL, 0, 0,
485 msg, str1, str2);
486}
Daniel Veillard4255d502002-04-16 15:50:10 +0000487
Daniel Veillardc0826a72004-08-10 14:17:33 +0000488/**
489 * xmlSchemaGetOnymousTypeName:
490 * @attr: the attribute declaration/use
491 *
492 * Returns the name of the attribute; if the attribute
493 * is a reference, the name of the referenced global type will be returned.
494 */
495static const xmlChar *
496xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
497{
498 if (attr->ref != NULL)
499 return(attr->ref);
500 else
501 return(attr->name);
502}
503
504/**
505 * xmlSchemaGetOnymousTargetNsURI:
506 * @type: the type (element or attribute)
507 *
508 * Returns the target namespace URI of the type; if the type is a reference,
509 * the target namespace of the referenced type will be returned.
510 */
511static const xmlChar *
512xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
513{
514 if (attr->ref != NULL)
515 return (attr->refNs);
516 else
517 return(attr->targetNamespace);
518}
519
520/**
521 * xmlSchemaFormatNsUriLocal:
522 * @buf: the string buffer
523 * @uri: the namespace URI
524 * @local: the local name
525 *
526 * Returns a representation of the given URI used
527 * for error reports.
528 *
529 * Returns an empty string, if @ns is NULL, a formatted
530 * string otherwise.
531 */
532static const xmlChar*
533xmlSchemaFormatNsUriLocal(xmlChar **buf,
534 const xmlChar *uri, const xmlChar *local)
535{
536 if (*buf != NULL)
537 xmlFree(*buf);
538 if (uri == NULL) {
539 *buf = xmlStrdup(BAD_CAST "{'");
540 *buf = xmlStrcat(*buf, local);
541 } else {
542 *buf = xmlStrdup(BAD_CAST "{'");
543 *buf = xmlStrcat(*buf, uri);
544 *buf = xmlStrcat(*buf, BAD_CAST "', '");
545 *buf = xmlStrcat(*buf, local);
546 }
547 *buf = xmlStrcat(*buf, BAD_CAST "'}");
548 return ((const xmlChar *) *buf);
549}
550
551/**
552 * xmlSchemaFormatNsPrefixLocal:
553 * @buf: the string buffer
554 * @ns: the namespace
555 * @local: the local name
556 *
557 * Returns a representation of the given URI used
558 * for error reports.
559 *
560 * Returns an empty string, if @ns is NULL, a formatted
561 * string otherwise.
562 */
563static const xmlChar*
564xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
565 xmlNsPtr ns, const xmlChar *local)
566{
567 if (*buf != NULL) {
568 xmlFree(*buf);
569 *buf = NULL;
570 }
571 if ((ns == NULL) || (ns->prefix == NULL))
572 return(local);
573 else {
574 *buf = xmlStrdup(ns->prefix);
575 *buf = xmlStrcat(*buf, BAD_CAST ":");
576 *buf = xmlStrcat(*buf, local);
577 }
578 return ((const xmlChar *) *buf);
579}
580
581/**
582 * xmlSchemaFormatItemForReport:
583 * @buf: the string buffer
584 * @itemDes: the designation of the item
585 * @itemName: the name of the item
586 * @item: the item as an object
587 * @itemNode: the node of the item
588 * @local: the local name
589 * @parsing: if the function is used during the parse
590 *
591 * Returns a representation of the given item used
592 * for error reports.
593 *
594 * The following order is used to build the resulting
595 * designation if the arguments are not NULL:
596 * 1a. If itemDes not NULL -> itemDes
597 * 1b. If (itemDes not NULL) and (itemName not NULL)
598 * -> itemDes + itemName
599 * 2. If the preceding was NULL and (item not NULL) -> item
600 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
601 *
602 * If the itemNode is an attribute node, the name of the attribute
603 * will be appended to the result.
604 *
605 * Returns the formatted string and sets @buf to the resulting value.
606 */
607static xmlChar*
608xmlSchemaFormatItemForReport(xmlChar **buf,
609 const xmlChar *itemDes,
610 xmlSchemaTypePtr item,
611 xmlNodePtr itemNode,
612 int parsing)
613{
614 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000615 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000616
617 if (*buf != NULL) {
618 xmlFree(*buf);
619 *buf = NULL;
620 }
621
William M. Brack2f2a6632004-08-20 23:09:47 +0000622 if (itemDes != NULL) {
623 *buf = xmlStrdup(itemDes);
624 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000625 if (item->type == XML_SCHEMA_TYPE_BASIC) {
626 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
627 *buf = xmlStrdup(BAD_CAST "'anyType'");
628 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
629 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
630 else {
631 /* *buf = xmlStrdup(BAD_CAST "bi "); */
632 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
633 *buf = xmlStrdup(BAD_CAST "'");
634 *buf = xmlStrcat(*buf, item->name);
635 *buf = xmlStrcat(*buf, BAD_CAST "'");
636 }
637 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
638 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
639 *buf = xmlStrdup(xmlSchemaElemDesST);
640 *buf = xmlStrcat(*buf, BAD_CAST " '");
641 *buf = xmlStrcat(*buf, item->name);
642 *buf = xmlStrcat(*buf, BAD_CAST "'");
643 } else {
644 *buf = xmlStrdup(xmlSchemaElemDesST);
645 *buf = xmlStrcat(*buf, BAD_CAST " local");
646 }
647 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
648 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
649 *buf = xmlStrdup(xmlSchemaElemDesCT);
650 *buf = xmlStrcat(*buf, BAD_CAST " '");
651 *buf = xmlStrcat(*buf, item->name);
652 *buf = xmlStrcat(*buf, BAD_CAST "'");
653 } else {
654 *buf = xmlStrdup(xmlSchemaElemDesCT);
655 *buf = xmlStrcat(*buf, BAD_CAST " local");
656 }
657 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
658 xmlSchemaAttributePtr attr;
659
660 attr = (xmlSchemaAttributePtr) item;
661 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
662 (attr->ref == NULL)) {
663 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
664 *buf = xmlStrcat(*buf, BAD_CAST " '");
665 *buf = xmlStrcat(*buf, attr->name);
666 *buf = xmlStrcat(*buf, BAD_CAST "'");
667 } else {
668 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
669 *buf = xmlStrcat(*buf, BAD_CAST " '");
670 *buf = xmlStrcat(*buf, attr->refPrefix);
671 *buf = xmlStrcat(*buf, BAD_CAST ":");
672 *buf = xmlStrcat(*buf, attr->ref);
673 *buf = xmlStrcat(*buf, BAD_CAST "'");
674 }
675 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
676 xmlSchemaElementPtr elem;
677
678 elem = (xmlSchemaElementPtr) item;
679 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
680 (elem->ref == NULL)) {
681 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
682 *buf = xmlStrcat(*buf, BAD_CAST " '");
683 *buf = xmlStrcat(*buf, elem->name);
684 *buf = xmlStrcat(*buf, BAD_CAST "'");
685 } else {
686 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
687 *buf = xmlStrcat(*buf, BAD_CAST " '");
688 *buf = xmlStrcat(*buf, elem->refPrefix);
689 *buf = xmlStrcat(*buf, BAD_CAST ":");
690 *buf = xmlStrcat(*buf, elem->ref);
691 *buf = xmlStrcat(*buf, BAD_CAST "'");
692 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000693 } else
694 named = 0;
695 } else
696 named = 0;
697
698 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000699 xmlNodePtr elem;
700
701 if (itemNode->type == XML_ATTRIBUTE_NODE)
702 elem = itemNode->parent;
703 else
704 elem = itemNode;
705 *buf = xmlStrdup(BAD_CAST "Element '");
706 if (parsing)
707 *buf = xmlStrcat(*buf, elem->name);
708 else
709 *buf = xmlStrcat(*buf,
710 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
711 *buf = xmlStrcat(*buf, BAD_CAST "'");
712 }
713 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
714 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
715 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
716 itemNode->ns, itemNode->name));
717 *buf = xmlStrcat(*buf, BAD_CAST "'");
718 }
719 FREE_AND_NULL(str);
720
721 return (*buf);
722}
723
724/**
725 * xmlSchemaPFormatItemDes:
726 * @buf: the string buffer
727 * @item: the item as a schema object
728 * @itemNode: the item as a node
729 *
730 * If the pointer to @buf is not NULL and @but holds no value,
731 * the value is set to a item designation using
732 * xmlSchemaFormatItemForReport. This one avoids adding
733 * an attribute designation postfix.
734 *
735 * Returns a string of all enumeration elements.
736 */
737static void
738xmlSchemaPRequestItemDes(xmlChar **buf,
739 xmlSchemaTypePtr item,
740 xmlNodePtr itemNode)
741{
742 if ((buf == 0) || (*buf != NULL))
743 return;
744 if (itemNode->type == XML_ATTRIBUTE_NODE)
745 itemNode = itemNode->parent;
746 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
747}
748
749/**
750 * xmlSchemaFormatFacetEnumSet:
751 * @buf: the string buffer
752 * @type: the type holding the enumeration facets
753 *
754 * Builds a string consisting of all enumeration elements.
755 *
756 * Returns a string of all enumeration elements.
757 */
758static const xmlChar *
759xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
760{
761 xmlSchemaFacetLinkPtr link;
762
763 if (*buf != NULL)
764 xmlFree(*buf);
765 *buf = NULL;
766 for (link = type->facetSet; link != NULL; link = link->next) {
767 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
768 if (*buf == NULL) {
769 *buf = xmlStrdup(BAD_CAST "'");
770 *buf = xmlStrcat(*buf, link->facet->value);
771 *buf = xmlStrcat(*buf, BAD_CAST "'");
772 } else {
773 *buf = xmlStrcat(*buf, BAD_CAST ", '");
774 *buf = xmlStrcat(*buf, link->facet->value);
775 *buf = xmlStrcat(*buf, BAD_CAST "'");
776 }
777 }
778 }
779 return ((const xmlChar *) *buf);
780}
781
782/**
783 * xmlSchemaVFacetErr:
784 * @ctxt: the schema validation context
785 * @error: the error code
786 * @node: the node to be validated
787 * @value: the value of the node
788 * @type: the type holding the facet
789 * @facet: the facet
790 * @message: the error message of NULL
791 * @str1: extra data
792 * @str2: extra data
793 * @str3: extra data
794 *
795 * Reports a facet validation error.
796 * TODO: Should this report the value of an element as well?
797 */
798static void
799xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
800 xmlParserErrors error,
801 xmlNodePtr node,
802 const xmlChar *value,
803 unsigned long length,
804 xmlSchemaTypePtr type,
805 xmlSchemaFacetPtr facet,
806 const char *message,
807 const xmlChar *str1,
808 const xmlChar *str2,
809 const xmlChar *str3)
810{
811 xmlChar *str = NULL, *msg = NULL;
812 xmlSchemaTypeType facetType;
813
814 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
815 msg = xmlStrcat(msg, BAD_CAST " [");
816 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
817 msg = xmlStrcat(msg, BAD_CAST ", facet '");
818 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
819 facetType = XML_SCHEMA_FACET_ENUMERATION;
820 /*
821 * If enumerations are validated, one must not expect the
822 * facet to be given.
823 */
824 } else
825 facetType = facet->type;
826 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
827 msg = xmlStrcat(msg, BAD_CAST "']: ");
828 if (message == NULL) {
829 /*
830 * Use a default message.
831 */
832 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
833 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
834 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
835
836 char len[25], actLen[25];
837
838 /* FIXME, TODO: What is the max expected string length of the
839 * this value?
840 */
841 if (node->type == XML_ATTRIBUTE_NODE)
842 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
843 else
844 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
845
846 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
847 snprintf(actLen, 24, "%lu", length);
848
849 if (facetType == XML_SCHEMA_FACET_LENGTH)
850 msg = xmlStrcat(msg,
851 BAD_CAST "this differs from the allowed length of '%s'.\n");
852 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
853 msg = xmlStrcat(msg,
854 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
855 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
856 msg = xmlStrcat(msg,
857 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
858
859 if (node->type == XML_ATTRIBUTE_NODE)
860 xmlSchemaVErrExt(ctxt, node, error,
861 (const char *) msg,
862 value, (const xmlChar *) actLen, (const xmlChar *) len,
863 NULL, NULL);
864 else
865 xmlSchemaVErr(ctxt, node, error,
866 (const char *) msg,
867 (const xmlChar *) actLen, (const xmlChar *) len);
868
869 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
870 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
871 "of the set {%s}.\n");
872 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
873 xmlSchemaFormatFacetEnumSet(&str, type));
874 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
875 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
876 "by the pattern '%s'.\n");
877 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
878 facet->value);
879 } else if (node->type == XML_ATTRIBUTE_NODE) {
880 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
881 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
882 } else {
883 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
884 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
885 }
886 } else {
887 msg = xmlStrcat(msg, (const xmlChar *) message);
888 msg = xmlStrcat(msg, BAD_CAST ".\n");
889 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
890 }
891 FREE_AND_NULL(str)
892 xmlFree(msg);
893}
894
895/**
896 * xmlSchemaVSimpleTypeErr:
897 * @ctxt: the schema validation context
898 * @error: the error code
899 * @type: the type used for validation
900 * @node: the node containing the validated value
901 * @value: the validated value
902 *
903 * Reports a simple type validation error.
904 * TODO: Should this report the value of an element as well?
905 */
906static void
907xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
908 xmlParserErrors error,
909 xmlNodePtr node,
910 const xmlChar *value,
911 xmlSchemaTypePtr type)
912{
913 xmlChar *str = NULL, *msg = NULL;
914
915 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
916 msg = xmlStrcat(msg, BAD_CAST " [");
917 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
918 if (node->type == XML_ATTRIBUTE_NODE) {
919 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
920 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
921 } else {
922 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
923 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
924 }
925 FREE_AND_NULL(str)
926 xmlFree(msg);
927}
928
929/**
William M. Brack2f2a6632004-08-20 23:09:47 +0000930 * xmlSchemaVComplexTypeErr:
931 * @ctxt: the schema validation context
932 * @error: the error code
933 * @node: the node containing the validated value
934 * @type: the complex type used for validation
935 * @message: the error message
936 *
937 * Reports a complex type validation error.
938 */
939static void
940xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
941 xmlParserErrors error,
942 xmlNodePtr node,
943 xmlSchemaTypePtr type,
944 const char *message)
945{
946 xmlChar *str = NULL, *msg = NULL;
947
948 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
949 msg = xmlStrcat(msg, BAD_CAST " [");
950 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
951 msg = xmlStrcat(msg, BAD_CAST "]: %s.\n");
952 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
953 (const xmlChar *) message, NULL);
954 FREE_AND_NULL(str)
955 xmlFree(msg);
956}
957
958/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000959 * xmlSchemaPMissingAttrErr:
960 * @ctxt: the schema validation context
961 * @ownerDes: the designation of the owner
962 * @ownerName: the name of the owner
963 * @ownerItem: the owner as a schema object
964 * @ownerElem: the owner as an element node
965 * @node: the parent element node of the missing attribute node
966 * @type: the corresponding type of the attribute node
967 *
968 * Reports an illegal attribute.
969 */
970static void
971xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
972 xmlParserErrors error,
973 xmlChar **ownerDes,
974 xmlSchemaTypePtr ownerItem,
975 xmlNodePtr ownerElem,
976 const char *name,
977 const char *message)
978{
979 xmlChar *des = NULL;
980
981 if (ownerDes == NULL)
982 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
983 else if (*ownerDes == NULL) {
984 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
985 des = *ownerDes;
986 } else
987 des = *ownerDes;
988 if (message != NULL)
989 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
990 else
991 xmlSchemaPErr(ctxt, ownerElem, error,
992 "%s: The attribute '%s' is required but missing.\n",
993 BAD_CAST des, BAD_CAST name);
994 if (ownerDes == NULL)
995 FREE_AND_NULL(des);
996}
997
William M. Brack2f2a6632004-08-20 23:09:47 +0000998/**
999 * xmlSchemaCompTypeToString:
1000 * @type: the type of the schema item
1001 *
1002 * Returns the component name of a schema item.
1003 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001004static const char *
1005xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1006{
1007 switch (type) {
1008 case XML_SCHEMA_TYPE_SIMPLE:
1009 return("simple type definition");
1010 case XML_SCHEMA_TYPE_COMPLEX:
1011 return("complex type definition");
1012 case XML_SCHEMA_TYPE_ELEMENT:
1013 return("element declaration");
1014 case XML_SCHEMA_TYPE_ATTRIBUTE:
1015 return("attribute declaration");
1016 case XML_SCHEMA_TYPE_GROUP:
1017 return("model group definition");
1018 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1019 return("attribute group definition");
1020 case XML_SCHEMA_TYPE_NOTATION:
1021 return("notation declaration");
1022 default:
1023 return("Not a schema component");
1024 }
1025}
1026/**
1027 * xmlSchemaPResCompAttrErr:
1028 * @ctxt: the schema validation context
1029 * @error: the error code
1030 * @ownerDes: the designation of the owner
1031 * @ownerItem: the owner as a schema object
1032 * @ownerElem: the owner as an element node
1033 * @name: the name of the attribute holding the QName
1034 * @refName: the referenced local name
1035 * @refURI: the referenced namespace URI
1036 * @message: optional message
1037 *
1038 * Used to report QName attribute values that failed to resolve
1039 * to schema components.
1040 */
1041static void
1042xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1043 xmlParserErrors error,
1044 xmlChar **ownerDes,
1045 xmlSchemaTypePtr ownerItem,
1046 xmlNodePtr ownerElem,
1047 const char *name,
1048 const xmlChar *refName,
1049 const xmlChar *refURI,
1050 xmlSchemaTypeType refType,
1051 const char *refTypeStr)
1052{
1053 xmlChar *des = NULL, *strA = NULL;
1054
1055 if (ownerDes == NULL)
1056 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1057 else if (*ownerDes == NULL) {
1058 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1059 des = *ownerDes;
1060 } else
1061 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001062 if (refTypeStr == NULL)
1063 refTypeStr = xmlSchemaCompTypeToString(refType);
1064 xmlSchemaPErrExt(ctxt, ownerElem, error,
1065 NULL, NULL, NULL,
1066 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1067 "%s.\n", BAD_CAST des, BAD_CAST name,
1068 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1069 BAD_CAST refTypeStr, NULL);
1070 if (ownerDes == NULL)
1071 FREE_AND_NULL(des)
1072 FREE_AND_NULL(strA)
1073}
1074
William M. Brack2f2a6632004-08-20 23:09:47 +00001075/**
1076 * xmlSchemaPCustomAttrErr:
1077 * @ctxt: the schema parser context
1078 * @error: the error code
1079 * @ownerDes: the designation of the owner
1080 * @ownerItem: the owner as a schema object
1081 * @attr: the illegal attribute node
1082 *
1083 * Reports an illegal attribute during the parse.
1084 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001085static void
1086xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001087 xmlParserErrors error,
1088 xmlChar **ownerDes,
1089 xmlSchemaTypePtr ownerItem,
1090 xmlAttrPtr attr,
1091 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001092{
1093 xmlChar *des = NULL;
1094
1095 if (ownerDes == NULL)
1096 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1097 else if (*ownerDes == NULL) {
1098 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1099 des = *ownerDes;
1100 } else
1101 des = *ownerDes;
1102 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1103 "%s, attribute '%s': %s.\n",
1104 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1105 if (ownerDes == NULL)
1106 FREE_AND_NULL(des);
1107}
1108
1109/**
1110 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001111 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001112 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001113 * @ownerDes: the designation of the attribute's owner
1114 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001115 * @attr: the illegal attribute node
1116 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001117 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001118 */
1119static void
1120xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1121 xmlParserErrors error,
1122 xmlChar **ownerDes,
1123 xmlSchemaTypePtr ownerItem,
1124 xmlAttrPtr attr)
1125{
1126 xmlChar *des = NULL, *strA = NULL;
1127
1128 if (ownerDes == NULL)
1129 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1130 else if (*ownerDes == NULL) {
1131 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1132 des = *ownerDes;
1133 } else
1134 des = *ownerDes;
1135 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1136 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1137 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1138 if (ownerDes == NULL)
1139 FREE_AND_NULL(des);
1140 FREE_AND_NULL(strA);
1141}
1142
William M. Brack2f2a6632004-08-20 23:09:47 +00001143/**
1144 * xmlSchemaPAquireDes:
1145 * @des: the first designation
1146 * @itemDes: the second designation
1147 * @item: the schema item
1148 * @itemElem: the node of the schema item
1149 *
1150 * Creates a designation for an item.
1151 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001152static void
1153xmlSchemaPAquireDes(xmlChar **des,
1154 xmlChar **itemDes,
1155 xmlSchemaTypePtr item,
1156 xmlNodePtr itemElem)
1157{
1158 if (itemDes == NULL)
1159 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1160 else if (*itemDes == NULL) {
1161 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1162 *des = *itemDes;
1163 } else
1164 *des = *itemDes;
1165}
1166
William M. Brack2f2a6632004-08-20 23:09:47 +00001167/**
1168 * xmlSchemaPCustomErr:
1169 * @ctxt: the schema parser context
1170 * @error: the error code
1171 * @itemDes: the designation of the schema item
1172 * @item: the schema item
1173 * @itemElem: the node of the schema item
1174 * @message: the error message
1175 * @str1: an optional param for the error message
1176 * @str2: an optional param for the error message
1177 * @str3: an optional param for the error message
1178 *
1179 * Reports an error during parsing.
1180 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001181static void
1182xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1183 xmlParserErrors error,
1184 xmlChar **itemDes,
1185 xmlSchemaTypePtr item,
1186 xmlNodePtr itemElem,
1187 const char *message,
1188 const xmlChar *str1,
1189 const xmlChar *str2,
1190 const xmlChar *str3)
1191{
1192 xmlChar *des = NULL, *msg = NULL;
1193
1194 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1195 msg = xmlStrdup(BAD_CAST "%s: ");
1196 msg = xmlStrcat(msg, (const xmlChar *) message);
1197 msg = xmlStrcat(msg, BAD_CAST ".\n");
1198 if ((itemElem == NULL) && (item != NULL))
1199 itemElem = item->node;
1200 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1201 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1202 if (itemDes == NULL)
1203 FREE_AND_NULL(des);
1204 FREE_AND_NULL(msg);
1205}
1206
William M. Brack2f2a6632004-08-20 23:09:47 +00001207/**
1208 * xmlSchemaPCustomErr:
1209 * @ctxt: the schema parser context
1210 * @error: the error code
1211 * @itemDes: the designation of the schema item
1212 * @item: the schema item
1213 * @itemElem: the node of the schema item
1214 * @message: the error message
1215 * @str1: the optional param for the error message
1216 *
1217 * Reports an error during parsing.
1218 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001219static void
1220xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1221 xmlParserErrors error,
1222 xmlChar **itemDes,
1223 xmlSchemaTypePtr item,
1224 xmlNodePtr itemElem,
1225 const char *message,
1226 const xmlChar *str1)
1227{
1228 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1229 str1, NULL, NULL);
1230}
1231
William M. Brack2f2a6632004-08-20 23:09:47 +00001232/**
1233 * xmlSchemaPAttrUseErr:
1234 * @ctxt: the schema parser context
1235 * @error: the error code
1236 * @itemDes: the designation of the schema type
1237 * @item: the schema type
1238 * @itemElem: the node of the schema type
1239 * @attr: the invalid schema attribute
1240 * @message: the error message
1241 * @str1: the optional param for the error message
1242 *
1243 * Reports an attribute use error during parsing.
1244 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001245static void
1246xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1247 xmlParserErrors error,
1248 xmlChar **itemDes,
1249 xmlSchemaTypePtr item,
1250 xmlNodePtr itemElem,
1251 const xmlSchemaAttributePtr attr,
1252 const char *message,
1253 const xmlChar *str1)
1254{
1255 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1256
1257 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1258 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1259 xmlSchemaGetAttrName(attr));
1260 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1261 msg = xmlStrcat(msg, (const xmlChar *) message);
1262 msg = xmlStrcat(msg, BAD_CAST ".\n");
1263 if ((itemElem == NULL) && (item != NULL))
1264 itemElem = item->node;
1265 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1266 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1267 if (itemDes == NULL)
1268 FREE_AND_NULL(des);
1269 FREE_AND_NULL(strA);
1270 xmlFree(msg);
1271}
1272
William M. Brack2f2a6632004-08-20 23:09:47 +00001273/**
1274 * xmlSchemaPIllegalFacetAtomicErr:
1275 * @ctxt: the schema parser context
1276 * @error: the error code
1277 * @itemDes: the designation of the type
1278 * @item: the schema type
1279 * @baseItem: the base type of type
1280 * @facet: the illegal facet
1281 *
1282 * Reports an illegal facet for atomic simple types.
1283 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001284static void
1285xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1286 xmlParserErrors error,
1287 xmlChar **itemDes,
1288 xmlSchemaTypePtr item,
1289 xmlSchemaTypePtr baseItem,
1290 xmlSchemaFacetPtr facet)
1291{
1292 xmlChar *des = NULL, *strT = NULL;
1293
1294 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1295 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1296 "%s: The facet '%s' is not allowed on types derived from the "
1297 "type %s.\n",
1298 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1299 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1300 NULL, NULL);
1301 if (itemDes == NULL)
1302 FREE_AND_NULL(des);
1303 FREE_AND_NULL(strT);
1304}
1305
William M. Brack2f2a6632004-08-20 23:09:47 +00001306/**
1307 * xmlSchemaPIllegalFacetListUnionErr:
1308 * @ctxt: the schema parser context
1309 * @error: the error code
1310 * @itemDes: the designation of the schema item involved
1311 * @item: the schema item involved
1312 * @facet: the illegal facet
1313 *
1314 * Reports an illegal facet for <list> and <union>.
1315 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001316static void
1317xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1318 xmlParserErrors error,
1319 xmlChar **itemDes,
1320 xmlSchemaTypePtr item,
1321 xmlSchemaFacetPtr facet)
1322{
1323 xmlChar *des = NULL, *strT = NULL;
1324
1325 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1326 xmlSchemaPErr(ctxt, item->node, error,
1327 "%s: The facet '%s' is not allowed.\n",
1328 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1329 if (itemDes == NULL)
1330 FREE_AND_NULL(des);
1331 FREE_AND_NULL(strT);
1332}
1333
1334/**
1335 * xmlSchemaPMutualExclAttrErr:
1336 * @ctxt: the schema validation context
1337 * @error: the error code
1338 * @elemDes: the designation of the parent element node
1339 * @attr: the bad attribute node
1340 * @type: the corresponding type of the attribute node
1341 *
1342 * Reports an illegal attribute.
1343 */
1344static void
1345xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1346 xmlParserErrors error,
1347 xmlChar **ownerDes,
1348 xmlSchemaTypePtr ownerItem,
1349 xmlAttrPtr attr,
1350 const char *name1,
1351 const char *name2)
1352{
1353 xmlChar *des = NULL;
1354
1355 if (ownerDes == NULL)
1356 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1357 else if (*ownerDes == NULL) {
1358 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1359 des = *ownerDes;
1360 } else
1361 des = *ownerDes;
1362 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1363 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1364 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1365 if (ownerDes == NULL)
1366 FREE_AND_NULL(des)
1367}
1368
1369/**
1370 * xmlSchemaPSimpleTypeErr:
1371 * @ctxt: the schema validation context
1372 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001373 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001374 * @ownerDes: the designation of the owner
1375 * @ownerItem: the schema object if existent
1376 * @node: the validated node
1377 * @value: the validated value
1378 *
1379 * Reports a simple type validation error.
1380 * TODO: Should this report the value of an element as well?
1381 */
1382static void
1383xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1384 xmlParserErrors error,
1385 xmlChar **ownerDes,
1386 xmlSchemaTypePtr ownerItem,
1387 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001388 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001389 const char *typeDes,
1390 const xmlChar *value,
1391 const char *message,
1392 const xmlChar *str1,
1393 const xmlChar *str2)
1394{
William M. Brack2f2a6632004-08-20 23:09:47 +00001395 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001396
1397 if (ownerDes == NULL)
1398 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1399 else if (*ownerDes == NULL) {
1400 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1401 des = *ownerDes;
1402 } else
1403 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001404 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001405 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001406 if (message == NULL) {
1407 /*
1408 * Use default messages.
1409 */
1410 if (node->type == XML_ATTRIBUTE_NODE) {
1411 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1412 "%s, attribute '%s' [%s]: The value '%s' is not "
1413 "valid.\n",
1414 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1415 node->name), BAD_CAST typeDes, value, NULL);
1416 } else {
1417 xmlSchemaPErr(ctxt, node, error,
1418 "%s [%s]: The character content is not valid.\n",
1419 BAD_CAST des, BAD_CAST typeDes);
1420 }
1421 } else {
1422 xmlChar *msg;
1423
1424 msg = xmlStrdup(BAD_CAST "%s");
1425 if (node->type == XML_ATTRIBUTE_NODE)
1426 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1427 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1428 msg = xmlStrcat(msg, (const xmlChar *) message);
1429 msg = xmlStrcat(msg, BAD_CAST ".\n");
1430 if (node->type == XML_ATTRIBUTE_NODE) {
1431 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1432 (const char *) msg,
1433 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1434 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1435 } else {
1436 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1437 (const char *) msg,
1438 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1439 }
1440 xmlFree(msg);
1441 }
1442 /* Cleanup. */
1443 FREE_AND_NULL(strA)
1444 FREE_AND_NULL(strT)
1445 if (ownerDes == NULL)
1446 FREE_AND_NULL(des)
1447}
1448
William M. Brack2f2a6632004-08-20 23:09:47 +00001449/**
1450 * xmlSchemaPContentErr:
1451 * @ctxt: the schema parser context
1452 * @error: the error code
1453 * @onwerDes: the designation of the holder of the content
1454 * @ownerItem: the owner item of the holder of the content
1455 * @ownerElem: the node of the holder of the content
1456 * @child: the invalid child node
1457 * @message: the optional error message
1458 * @content: the optional string describing the correct content
1459 *
1460 * Reports an error concerning the content of a schema element.
1461 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001462static void
1463xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1464 xmlParserErrors error,
1465 xmlChar **ownerDes,
1466 xmlSchemaTypePtr ownerItem,
1467 xmlNodePtr ownerElem,
1468 xmlNodePtr child,
1469 const char *message,
1470 const char *content)
1471{
1472 xmlChar *des = NULL;
1473
1474 if (ownerDes == NULL)
1475 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1476 else if (*ownerDes == NULL) {
1477 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1478 des = *ownerDes;
1479 } else
1480 des = *ownerDes;
1481 if (message != NULL)
1482 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1483 "%s: %s.\n",
1484 BAD_CAST des, BAD_CAST message);
1485 else {
1486 if (content != NULL) {
1487 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1488 "%s: The content is not valid. Expected is %s.\n",
1489 BAD_CAST des, BAD_CAST content);
1490 } else {
1491 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1492 "%s: The content is not valid.\n",
1493 BAD_CAST des, NULL);
1494 }
1495 }
1496 if (ownerDes == NULL)
1497 FREE_AND_NULL(des)
1498}
1499
1500/**
1501 * xmlSchemaVIllegalAttrErr:
1502 * @ctxt: the schema validation context
1503 * @attr: the illegal attribute node
1504 *
1505 * Reports an illegal attribute.
1506 */
1507static void
1508xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001509 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001510{
1511 xmlChar *strE = NULL, *strA = NULL;
1512
1513 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1514 XML_SCHEMAS_ERR_ATTRUNKNOWN,
1515 "%s: The attribute '%s' is not allowed.\n",
1516 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1517 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1518 FREE_AND_NULL(strE)
1519 FREE_AND_NULL(strA)
1520}
1521
William M. Brack2f2a6632004-08-20 23:09:47 +00001522/**
1523 * xmlSchemaVCustomErr:
1524 * @ctxt: the schema validation context
1525 * @error: the error code
1526 * @node: the validated node
1527 * @message: the error message
1528 * @str1: the optional param for the message
1529 *
1530 * Reports a validation error.
1531 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001532static void
1533xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1534 xmlParserErrors error,
1535 xmlNodePtr node,
1536 const char *message,
1537 const xmlChar *str1)
1538{
1539 xmlChar *des = NULL, *msg = NULL;
1540
1541 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1542 msg = xmlStrdup(BAD_CAST "%s: ");
1543 msg = xmlStrcat(msg, (const xmlChar *) message);
1544 msg = xmlStrcat(msg, BAD_CAST ".\n");
1545 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg,
1546 BAD_CAST des, str1, NULL, NULL, NULL);
1547 FREE_AND_NULL(des);
1548 FREE_AND_NULL(msg);
1549}
1550
William M. Brack2f2a6632004-08-20 23:09:47 +00001551/**
1552 * xmlSchemaWildcardPCToString:
1553 * @pc: the type of processContents
1554 *
1555 * Returns a string representation of the type of
1556 * processContents.
1557 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001558static const char *
1559xmlSchemaWildcardPCToString(int pc)
1560{
1561 switch (pc) {
1562 case XML_SCHEMAS_ANY_SKIP:
1563 return ("skip");
1564 case XML_SCHEMAS_ANY_LAX:
1565 return ("lax");
1566 case XML_SCHEMAS_ANY_STRICT:
1567 return ("strict");
1568 default:
1569 return ("invalid process contents");
1570 }
1571}
1572
William M. Brack2f2a6632004-08-20 23:09:47 +00001573/**
1574 * xmlSchemaVWildcardErr:
1575 * @ctxt: the schema validation context
1576 * @error: the error code
1577 * @node: the validated node
1578 * @wild: the wildcard used
1579 * @message: the error message
1580 *
1581 * Reports an validation-by-wildcard error.
1582 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001583static void
1584xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1585 xmlParserErrors error,
1586 xmlNodePtr node,
1587 xmlSchemaWildcardPtr wild,
1588 const char *message)
1589{
1590 xmlChar *des = NULL, *msg = NULL;
1591
1592 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1593 msg = xmlStrdup(BAD_CAST "%s, [");
1594 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1595 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1596 msg = xmlStrcat(msg, (const xmlChar *) message);
1597 msg = xmlStrcat(msg, BAD_CAST ".\n");
1598 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1599 FREE_AND_NULL(des);
1600 FREE_AND_NULL(msg);
1601}
1602
1603/**
1604 * xmlSchemaVMissingAttrErr:
1605 * @ctxt: the schema validation context
1606 * @node: the parent element node of the missing attribute node
1607 * @type: the corresponding type of the attribute node
1608 *
1609 * Reports an illegal attribute.
1610 */
1611static void
1612xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1613 xmlNodePtr elem,
1614 xmlSchemaAttributePtr type)
1615{
1616 const xmlChar *name, *uri;
1617 xmlChar *strE = NULL, *strA = NULL;
1618
1619 if (type->ref != NULL) {
1620 name = type->ref;
1621 uri = type->refNs;
1622 } else {
1623 name = type->name;
1624 uri = type->targetNamespace;
1625 }
1626 xmlSchemaVErr(ctxt, elem,
1627 XML_SCHEMAS_ERR_MISSING,
1628 "%s: The attribute %s is required but missing.\n",
1629 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1630 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1631 FREE_AND_NULL(strE)
1632 FREE_AND_NULL(strA)
1633}
1634
Daniel Veillard4255d502002-04-16 15:50:10 +00001635/************************************************************************
1636 * *
1637 * Allocation functions *
1638 * *
1639 ************************************************************************/
1640
1641/**
1642 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +00001643 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001644 *
1645 * Allocate a new Schema structure.
1646 *
1647 * Returns the newly allocated structure or NULL in case or error
1648 */
1649static xmlSchemaPtr
1650xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1651{
1652 xmlSchemaPtr ret;
1653
1654 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1655 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001656 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001657 return (NULL);
1658 }
1659 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001660 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001661 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001662
1663 return (ret);
1664}
1665
1666/**
1667 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001668 *
1669 * Allocate a new Facet structure.
1670 *
1671 * Returns the newly allocated structure or NULL in case or error
1672 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001673xmlSchemaFacetPtr
1674xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001675{
1676 xmlSchemaFacetPtr ret;
1677
1678 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1679 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001680 return (NULL);
1681 }
1682 memset(ret, 0, sizeof(xmlSchemaFacet));
1683
1684 return (ret);
1685}
1686
1687/**
1688 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001689 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001690 * @node: a node
1691 *
1692 * Allocate a new annotation structure.
1693 *
1694 * Returns the newly allocated structure or NULL in case or error
1695 */
1696static xmlSchemaAnnotPtr
1697xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1698{
1699 xmlSchemaAnnotPtr ret;
1700
1701 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1702 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001703 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001704 return (NULL);
1705 }
1706 memset(ret, 0, sizeof(xmlSchemaAnnot));
1707 ret->content = node;
1708 return (ret);
1709}
1710
1711/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001712 * xmlSchemaFreeAnnot:
1713 * @annot: a schema type structure
1714 *
1715 * Deallocate a annotation structure
1716 */
1717static void
1718xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1719{
1720 if (annot == NULL)
1721 return;
1722 xmlFree(annot);
1723}
1724
1725/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001726 * xmlSchemaFreeImport:
1727 * @import: a schema import structure
1728 *
1729 * Deallocate an import structure
1730 */
1731static void
1732xmlSchemaFreeImport(xmlSchemaImportPtr import)
1733{
1734 if (import == NULL)
1735 return;
1736
1737 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001738 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001739 xmlFree(import);
1740}
1741
1742/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001743 * xmlSchemaFreeInclude:
1744 * @include: a schema include structure
1745 *
1746 * Deallocate an include structure
1747 */
1748static void
1749xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1750{
1751 if (include == NULL)
1752 return;
1753
1754 xmlFreeDoc(include->doc);
1755 xmlFree(include);
1756}
1757
1758/**
1759 * xmlSchemaFreeIncludeList:
1760 * @includes: a schema include list
1761 *
1762 * Deallocate an include structure
1763 */
1764static void
1765xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1766{
1767 xmlSchemaIncludePtr next;
1768
1769 while (includes != NULL) {
1770 next = includes->next;
1771 xmlSchemaFreeInclude(includes);
1772 includes = next;
1773 }
1774}
1775
1776/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001777 * xmlSchemaFreeNotation:
1778 * @schema: a schema notation structure
1779 *
1780 * Deallocate a Schema Notation structure.
1781 */
1782static void
1783xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1784{
1785 if (nota == NULL)
1786 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001787 xmlFree(nota);
1788}
1789
1790/**
1791 * xmlSchemaFreeAttribute:
1792 * @schema: a schema attribute structure
1793 *
1794 * Deallocate a Schema Attribute structure.
1795 */
1796static void
1797xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1798{
1799 if (attr == NULL)
1800 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001801 if (attr->annot != NULL)
1802 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001803 xmlFree(attr);
1804}
1805
1806/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001807 * xmlSchemaFreeWildcardNsSet:
1808 * set: a schema wildcard namespace
1809 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001810 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001811 */
1812static void
1813xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1814{
1815 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001816
Daniel Veillard3646d642004-06-02 19:19:14 +00001817 while (set != NULL) {
1818 next = set->next;
1819 xmlFree(set);
1820 set = next;
1821 }
1822}
1823
1824/**
1825 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001826 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001827 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001828 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001829 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001830void
Daniel Veillard3646d642004-06-02 19:19:14 +00001831xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
1832{
1833 if (wildcard == NULL)
1834 return;
1835 if (wildcard->annot != NULL)
1836 xmlSchemaFreeAnnot(wildcard->annot);
1837 if (wildcard->nsSet != NULL)
1838 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
1839 if (wildcard->negNsSet != NULL)
1840 xmlFree(wildcard->negNsSet);
1841 xmlFree(wildcard);
1842}
1843
1844/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001845 * xmlSchemaFreeAttributeGroup:
1846 * @schema: a schema attribute group structure
1847 *
1848 * Deallocate a Schema Attribute Group structure.
1849 */
1850static void
1851xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
1852{
1853 if (attr == NULL)
1854 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00001855 if (attr->annot != NULL)
1856 xmlSchemaFreeAnnot(attr->annot);
1857 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
1858 (attr->attributeWildcard != NULL))
1859 xmlSchemaFreeWildcard(attr->attributeWildcard);
1860
Daniel Veillard4255d502002-04-16 15:50:10 +00001861 xmlFree(attr);
1862}
1863
1864/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001865 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001866 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00001867 *
1868 * Deallocate a list of schema attribute uses.
1869 */
1870static void
1871xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
1872{
1873 xmlSchemaAttributeLinkPtr next;
1874
1875 while (attrUse != NULL) {
1876 next = attrUse->next;
1877 xmlFree(attrUse);
1878 attrUse = next;
1879 }
1880}
1881
1882/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00001883 * xmlSchemaFreeTypeLinkList:
1884 * @alink: a type link
1885 *
1886 * Deallocate a list of types.
1887 */
1888static void
1889xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
1890{
1891 xmlSchemaTypeLinkPtr next;
1892
1893 while (link != NULL) {
1894 next = link->next;
1895 xmlFree(link);
1896 link = next;
1897 }
1898}
1899
1900/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001901 * xmlSchemaFreeElement:
1902 * @schema: a schema element structure
1903 *
1904 * Deallocate a Schema Element structure.
1905 */
1906static void
1907xmlSchemaFreeElement(xmlSchemaElementPtr elem)
1908{
1909 if (elem == NULL)
1910 return;
Daniel Veillard32370232002-10-16 14:08:14 +00001911 if (elem->annot != NULL)
1912 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001913 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001915 xmlFree(elem);
1916}
1917
1918/**
1919 * xmlSchemaFreeFacet:
1920 * @facet: a schema facet structure
1921 *
1922 * Deallocate a Schema Facet structure.
1923 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001924void
Daniel Veillard4255d502002-04-16 15:50:10 +00001925xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
1926{
1927 if (facet == NULL)
1928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001929 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001930 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001931 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001932 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00001933 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001934 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001935 xmlFree(facet);
1936}
1937
1938/**
1939 * xmlSchemaFreeType:
1940 * @type: a schema type structure
1941 *
1942 * Deallocate a Schema Type structure.
1943 */
1944void
1945xmlSchemaFreeType(xmlSchemaTypePtr type)
1946{
1947 if (type == NULL)
1948 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001949 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00001950 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001951 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001953
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001954 facet = type->facets;
1955 while (facet != NULL) {
1956 next = facet->next;
1957 xmlSchemaFreeFacet(facet);
1958 facet = next;
1959 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001960 }
Daniel Veillard3646d642004-06-02 19:19:14 +00001961 if (type->type != XML_SCHEMA_TYPE_BASIC) {
1962 if (type->attributeUses != NULL)
1963 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00001964 /* TODO: There must be a way more simple than this. */
Daniel Veillard3646d642004-06-02 19:19:14 +00001965 if ((type->attributeWildcard != NULL) &&
1966 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
1967 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
1968 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
1969 xmlSchemaFreeWildcard(type->attributeWildcard);
1970 }
1971 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00001972 if (type->memberTypes != NULL)
1973 xmlSchemaFreeTypeLinkList(type->memberTypes);
1974 if (type->facetSet != NULL) {
1975 xmlSchemaFacetLinkPtr next, link;
1976
1977 link = type->facetSet;
1978 do {
1979 next = link->next;
1980 xmlFree(link);
1981 link = next;
1982 } while (link != NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00001983 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001984 xmlFree(type);
1985}
1986
1987/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001988 * xmlSchemaFreeTypeList:
1989 * @type: a schema type structure
1990 *
1991 * Deallocate a Schema Type structure.
1992 */
1993static void
1994xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
1995{
1996 xmlSchemaTypePtr next;
1997
1998 while (type != NULL) {
1999 next = type->redef;
2000 xmlSchemaFreeType(type);
2001 type = next;
2002 }
2003}
2004
2005/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002006 * xmlSchemaFree:
2007 * @schema: a schema structure
2008 *
2009 * Deallocate a Schema structure.
2010 */
2011void
2012xmlSchemaFree(xmlSchemaPtr schema)
2013{
2014 if (schema == NULL)
2015 return;
2016
Daniel Veillard4255d502002-04-16 15:50:10 +00002017 if (schema->notaDecl != NULL)
2018 xmlHashFree(schema->notaDecl,
2019 (xmlHashDeallocator) xmlSchemaFreeNotation);
2020 if (schema->attrDecl != NULL)
2021 xmlHashFree(schema->attrDecl,
2022 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2023 if (schema->attrgrpDecl != NULL)
2024 xmlHashFree(schema->attrgrpDecl,
2025 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2026 if (schema->elemDecl != NULL)
2027 xmlHashFree(schema->elemDecl,
2028 (xmlHashDeallocator) xmlSchemaFreeElement);
2029 if (schema->typeDecl != NULL)
2030 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002031 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002032 if (schema->groupDecl != NULL)
2033 xmlHashFree(schema->groupDecl,
2034 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002035 if (schema->schemasImports != NULL)
2036 xmlHashFree(schema->schemasImports,
2037 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002038 if (schema->includes != NULL) {
2039 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2040 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002041 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002042 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002043 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002044 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002045 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002046
2047 xmlFree(schema);
2048}
2049
2050/************************************************************************
2051 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002052 * Debug functions *
2053 * *
2054 ************************************************************************/
2055
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002056#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002057
Daniel Veillard4255d502002-04-16 15:50:10 +00002058/**
2059 * xmlSchemaElementDump:
2060 * @elem: an element
2061 * @output: the file output
2062 *
2063 * Dump the element
2064 */
2065static void
2066xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002067 const xmlChar * name ATTRIBUTE_UNUSED,
2068 const xmlChar * context ATTRIBUTE_UNUSED,
2069 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002070{
2071 if (elem == NULL)
2072 return;
2073
2074 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002075 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2076 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002077 fprintf(output, ": %s ", elem->name);
2078 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002079 fprintf(output, "namespace '%s' ", namespace);
2080
Daniel Veillard4255d502002-04-16 15:50:10 +00002081 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002082 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002083 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002084 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002085 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002086 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002087 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002088 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002090 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002091 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002092 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002093 fprintf(output, "\n");
2094 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002095 fprintf(output, " ");
2096 if (elem->minOccurs != 1)
2097 fprintf(output, "min: %d ", elem->minOccurs);
2098 if (elem->maxOccurs >= UNBOUNDED)
2099 fprintf(output, "max: unbounded\n");
2100 else if (elem->maxOccurs != 1)
2101 fprintf(output, "max: %d\n", elem->maxOccurs);
2102 else
2103 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002104 }
2105 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002106 fprintf(output, " type: %s", elem->namedType);
2107 if (elem->namedTypeNs != NULL)
2108 fprintf(output, " ns %s\n", elem->namedTypeNs);
2109 else
2110 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002111 }
2112 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002113 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2114 if (elem->substGroupNs != NULL)
2115 fprintf(output, " ns %s\n", elem->substGroupNs);
2116 else
2117 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002118 }
2119 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002120 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002121}
2122
2123/**
2124 * xmlSchemaAnnotDump:
2125 * @output: the file output
2126 * @annot: a annotation
2127 *
2128 * Dump the annotation
2129 */
2130static void
2131xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2132{
2133 xmlChar *content;
2134
2135 if (annot == NULL)
2136 return;
2137
2138 content = xmlNodeGetContent(annot->content);
2139 if (content != NULL) {
2140 fprintf(output, " Annot: %s\n", content);
2141 xmlFree(content);
2142 } else
2143 fprintf(output, " Annot: empty\n");
2144}
2145
2146/**
2147 * xmlSchemaTypeDump:
2148 * @output: the file output
2149 * @type: a type structure
2150 *
2151 * Dump a SchemaType structure
2152 */
2153static void
2154xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2155{
2156 if (type == NULL) {
2157 fprintf(output, "Type: NULL\n");
2158 return;
2159 }
2160 fprintf(output, "Type: ");
2161 if (type->name != NULL)
2162 fprintf(output, "%s, ", type->name);
2163 else
2164 fprintf(output, "no name");
2165 switch (type->type) {
2166 case XML_SCHEMA_TYPE_BASIC:
2167 fprintf(output, "basic ");
2168 break;
2169 case XML_SCHEMA_TYPE_SIMPLE:
2170 fprintf(output, "simple ");
2171 break;
2172 case XML_SCHEMA_TYPE_COMPLEX:
2173 fprintf(output, "complex ");
2174 break;
2175 case XML_SCHEMA_TYPE_SEQUENCE:
2176 fprintf(output, "sequence ");
2177 break;
2178 case XML_SCHEMA_TYPE_CHOICE:
2179 fprintf(output, "choice ");
2180 break;
2181 case XML_SCHEMA_TYPE_ALL:
2182 fprintf(output, "all ");
2183 break;
2184 case XML_SCHEMA_TYPE_UR:
2185 fprintf(output, "ur ");
2186 break;
2187 case XML_SCHEMA_TYPE_RESTRICTION:
2188 fprintf(output, "restriction ");
2189 break;
2190 case XML_SCHEMA_TYPE_EXTENSION:
2191 fprintf(output, "extension ");
2192 break;
2193 default:
2194 fprintf(output, "unknowntype%d ", type->type);
2195 break;
2196 }
2197 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002198 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002199 }
2200 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002201 case XML_SCHEMA_CONTENT_UNKNOWN:
2202 fprintf(output, "unknown ");
2203 break;
2204 case XML_SCHEMA_CONTENT_EMPTY:
2205 fprintf(output, "empty ");
2206 break;
2207 case XML_SCHEMA_CONTENT_ELEMENTS:
2208 fprintf(output, "element ");
2209 break;
2210 case XML_SCHEMA_CONTENT_MIXED:
2211 fprintf(output, "mixed ");
2212 break;
2213 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002214 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002215 break;
2216 case XML_SCHEMA_CONTENT_BASIC:
2217 fprintf(output, "basic ");
2218 break;
2219 case XML_SCHEMA_CONTENT_SIMPLE:
2220 fprintf(output, "simple ");
2221 break;
2222 case XML_SCHEMA_CONTENT_ANY:
2223 fprintf(output, "any ");
2224 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002225 }
2226 fprintf(output, "\n");
2227 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 fprintf(output, " ");
2229 if (type->minOccurs != 1)
2230 fprintf(output, "min: %d ", type->minOccurs);
2231 if (type->maxOccurs >= UNBOUNDED)
2232 fprintf(output, "max: unbounded\n");
2233 else if (type->maxOccurs != 1)
2234 fprintf(output, "max: %d\n", type->maxOccurs);
2235 else
2236 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002237 }
2238 if (type->annot != NULL)
2239 xmlSchemaAnnotDump(output, type->annot);
2240 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002241 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002242
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002243 fprintf(output, " subtypes: ");
2244 while (sub != NULL) {
2245 fprintf(output, "%s ", sub->name);
2246 sub = sub->next;
2247 }
2248 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 }
2250
2251}
2252
2253/**
2254 * xmlSchemaDump:
2255 * @output: the file output
2256 * @schema: a schema structure
2257 *
2258 * Dump a Schema structure.
2259 */
2260void
2261xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2262{
2263 if (schema == NULL) {
2264 fprintf(output, "Schemas: NULL\n");
2265 return;
2266 }
2267 fprintf(output, "Schemas: ");
2268 if (schema->name != NULL)
2269 fprintf(output, "%s, ", schema->name);
2270 else
2271 fprintf(output, "no name, ");
2272 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002273 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002274 else
2275 fprintf(output, "no target namespace");
2276 fprintf(output, "\n");
2277 if (schema->annot != NULL)
2278 xmlSchemaAnnotDump(output, schema->annot);
2279
2280 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2281 output);
2282 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002283 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002284}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002285#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002286
2287/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002288 * *
2289 * Utilities *
2290 * *
2291 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002292
Daniel Veillardc0826a72004-08-10 14:17:33 +00002293/**
2294 * xmlSchemaGetPropNode:
2295 * @node: the element node
2296 * @name: the name of the attribute
2297 *
2298 * Seeks an attribute with a name of @name in
2299 * no namespace.
2300 *
2301 * Returns the attribute or NULL if not present.
2302 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002303static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002304xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002305{
2306 xmlAttrPtr prop;
2307
Daniel Veillardc0826a72004-08-10 14:17:33 +00002308 if ((node == NULL) || (name == NULL))
2309 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002310 prop = node->properties;
2311 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002312 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2313 return(prop);
2314 prop = prop->next;
2315 }
2316 return (NULL);
2317}
2318
2319/**
2320 * xmlSchemaGetPropNodeNs:
2321 * @node: the element node
2322 * @uri: the uri
2323 * @name: the name of the attribute
2324 *
2325 * Seeks an attribute with a local name of @name and
2326 * a namespace URI of @uri.
2327 *
2328 * Returns the attribute or NULL if not present.
2329 */
2330static xmlAttrPtr
2331xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2332{
2333 xmlAttrPtr prop;
2334
2335 if ((node == NULL) || (name == NULL))
2336 return(NULL);
2337 prop = node->properties;
2338 while (prop != NULL) {
2339 if ((prop->ns != NULL) &&
2340 xmlStrEqual(prop->name, BAD_CAST name) &&
2341 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002342 return(prop);
2343 prop = prop->next;
2344 }
2345 return (NULL);
2346}
2347
2348static const xmlChar *
2349xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2350{
2351 xmlChar *val;
2352 const xmlChar *ret;
2353
2354 val = xmlNodeGetContent(node);
2355 if (val == NULL)
2356 return(NULL);
2357 ret = xmlDictLookup(ctxt->dict, val, -1);
2358 xmlFree(val);
2359 return(ret);
2360}
2361
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002362/**
2363 * xmlSchemaGetProp:
2364 * @ctxt: the parser context
2365 * @node: the node
2366 * @name: the property name
2367 *
2368 * Read a attribute value and internalize the string
2369 *
2370 * Returns the string or NULL if not present.
2371 */
2372static const xmlChar *
2373xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2374 const char *name)
2375{
2376 xmlChar *val;
2377 const xmlChar *ret;
2378
2379 val = xmlGetProp(node, BAD_CAST name);
2380 if (val == NULL)
2381 return(NULL);
2382 ret = xmlDictLookup(ctxt->dict, val, -1);
2383 xmlFree(val);
2384 return(ret);
2385}
2386
William M. Brack29aa7722004-05-12 00:27:56 +00002387#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002388/**
2389 * xmlSchemaGetNamespace:
2390 * @ctxt: the parser context
2391 * @schema: the schemas containing the declaration
2392 * @node: the node
2393 * @qname: the QName to analyze
2394 *
2395 * Find the namespace name for the given declaration.
2396 *
2397 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00002398 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002399 */
2400static const xmlChar *
2401xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2402 xmlNodePtr node, const xmlChar *qname,
2403 const xmlChar **namespace) {
2404 int len;
2405 const xmlChar *name, *prefix, *def = NULL;
2406 xmlNsPtr ns;
2407
2408 *namespace = NULL;
2409
William M. Bracke7091952004-05-11 15:09:58 +00002410 /* TODO: The following seems to be not correct here:
2411 * 1. The name of a declaration is a NCName, not a QName.
2412 * 2. The attribute "targetNamespace" is allowed for the
2413 * <schema> Element Information Item only.
2414 * 3. One cannot evaluate the target namespace, by the type
2415 * of declaration, since it is dependant on the xxxFormDefault
2416 * of <schema> and the form attribute of an <element> or <attribute>.
2417 */
2418
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002419 if (xmlStrEqual(node->name, BAD_CAST "element") ||
2420 xmlStrEqual(node->name, BAD_CAST "attribute") ||
2421 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
2422 xmlStrEqual(node->name, BAD_CAST "complexType")) {
2423 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
2424 }
2425
William M. Bracke7091952004-05-11 15:09:58 +00002426
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002427 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
2428 name = xmlSplitQName3(qname, &len);
2429 if (name == NULL) {
2430 if (def == NULL) {
2431 if (xmlStrEqual(node->name, BAD_CAST "element")) {
2432 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
2433 *namespace = schema->targetNamespace;
2434 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
2435 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
2436 *namespace = schema->targetNamespace;
2437 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
2438 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
2439 *namespace = schema->targetNamespace;
2440 }
2441 } else {
2442 *namespace = def;
2443 }
2444 return(qname);
2445 }
William M. Bracke7091952004-05-11 15:09:58 +00002446
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002447 name = xmlDictLookup(ctxt->dict, name, -1);
2448 prefix = xmlDictLookup(ctxt->dict, qname, len);
2449 if (def != NULL) {
2450 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
2451 "%s: presence of both prefix %s and targetNamespace\n",
2452 node->name, prefix);
2453 }
2454 ns = xmlSearchNs(node->doc, node, prefix);
2455 if (ns == NULL) {
2456 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 "%s: The QName prefix %s is undefined\n",
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002458 node->name, prefix);
2459 return(name);
2460 }
2461 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2462 return(name);
2463}
William M. Brack29aa7722004-05-12 00:27:56 +00002464#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002465
2466/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002467 * *
2468 * Parsing functions *
2469 * *
2470 ************************************************************************/
2471
2472/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002473 * xmlSchemaGetElem:
2474 * @schema: the schemas context
2475 * @name: the element name
2476 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00002477 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002478 *
2479 * Lookup a an element in the schemas or the accessible schemas
2480 *
2481 * Returns the element definition or NULL if not found.
2482 */
2483static xmlSchemaElementPtr
2484xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00002485 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002486{
2487 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002488
2489 if ((name == NULL) || (schema == NULL))
2490 return (NULL);
2491
Daniel Veillard3646d642004-06-02 19:19:14 +00002492
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002493 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002494 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002495 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002496 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002497 } else
2498 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002499 /*
2500 * This one was removed, since top level element declarations have
2501 * the target namespace specified in targetNamespace of the <schema>
2502 * information element, even if elementFormDefault is "unqualified".
2503 */
2504
2505 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002506 if (xmlStrEqual(namespace, schema->targetNamespace))
2507 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2508 else
2509 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002510 if ((ret != NULL) &&
2511 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002512 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002513 }
William M. Bracke7091952004-05-11 15:09:58 +00002514 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002515
William M. Brack2f2a6632004-08-20 23:09:47 +00002516 /*
2517 * Removed since imported components will be hold by the main schema only.
2518 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002519 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002520 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002521 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002522 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002523 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002524 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002525 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2526 return (ret);
2527 } else
2528 ret = NULL;
2529 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002530 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002531#ifdef DEBUG
2532 if (ret == NULL) {
2533 if (namespace == NULL)
2534 fprintf(stderr, "Unable to lookup type %s", name);
2535 else
2536 fprintf(stderr, "Unable to lookup type %s:%s", name,
2537 namespace);
2538 }
2539#endif
2540 return (ret);
2541}
2542
2543/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002544 * xmlSchemaGetType:
2545 * @schema: the schemas context
2546 * @name: the type name
2547 * @ns: the type namespace
2548 *
2549 * Lookup a type in the schemas or the predefined types
2550 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002551 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 */
2553static xmlSchemaTypePtr
2554xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002555 const xmlChar * namespace)
2556{
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 xmlSchemaTypePtr ret;
2558
2559 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002560 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002561 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002562 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002563 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002564 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002565 }
2566 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002567 if (ret != NULL)
2568 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002569 /*
2570 * Removed, since the imported components will be grafted on the
2571 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002572 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002573 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002574 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002575 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002576 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002577 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002578 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2579 return (ret);
2580 } else
2581 ret = NULL;
2582 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002583 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002584#ifdef DEBUG
2585 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002586 if (namespace == NULL)
2587 fprintf(stderr, "Unable to lookup type %s", name);
2588 else
2589 fprintf(stderr, "Unable to lookup type %s:%s", name,
2590 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002591 }
2592#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002593 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002594}
2595
Daniel Veillard3646d642004-06-02 19:19:14 +00002596/**
2597 * xmlSchemaGetAttribute:
2598 * @schema: the context of the schema
2599 * @name: the name of the attribute
2600 * @ns: the target namespace of the attribute
2601 *
2602 * Lookup a an attribute in the schema or imported schemas
2603 *
2604 * Returns the attribute declaration or NULL if not found.
2605 */
2606static xmlSchemaAttributePtr
2607xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2608 const xmlChar * namespace)
2609{
2610 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002611
2612 if ((name == NULL) || (schema == NULL))
2613 return (NULL);
2614
2615
2616 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2617 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2618 return (ret);
2619 else
2620 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002621 /*
2622 * Removed, since imported components will be hold by the main schema only.
2623 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002624 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002625 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002626 else
2627 import = xmlHashLookup(schema->schemasImports, namespace);
2628 if (import != NULL) {
2629 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2630 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2631 return (ret);
2632 } else
2633 ret = NULL;
2634 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002635 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002636#ifdef DEBUG
2637 if (ret == NULL) {
2638 if (namespace == NULL)
2639 fprintf(stderr, "Unable to lookup attribute %s", name);
2640 else
2641 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2642 namespace);
2643 }
2644#endif
2645 return (ret);
2646}
2647
2648/**
2649 * xmlSchemaGetAttributeGroup:
2650 * @schema: the context of the schema
2651 * @name: the name of the attribute group
2652 * @ns: the target namespace of the attribute group
2653 *
2654 * Lookup a an attribute group in the schema or imported schemas
2655 *
2656 * Returns the attribute group definition or NULL if not found.
2657 */
2658static xmlSchemaAttributeGroupPtr
2659xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2660 const xmlChar * namespace)
2661{
2662 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002663
2664 if ((name == NULL) || (schema == NULL))
2665 return (NULL);
2666
2667
2668 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2669 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2670 return (ret);
2671 else
2672 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002673 /*
2674 * Removed since imported components will be hold by the main schema only.
2675 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002676 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002677 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002678 else
2679 import = xmlHashLookup(schema->schemasImports, namespace);
2680 if (import != NULL) {
2681 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2682 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2683 return (ret);
2684 else
2685 ret = NULL;
2686 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002687 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002688#ifdef DEBUG
2689 if (ret == NULL) {
2690 if (namespace == NULL)
2691 fprintf(stderr, "Unable to lookup attribute group %s", name);
2692 else
2693 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2694 namespace);
2695 }
2696#endif
2697 return (ret);
2698}
2699
2700/**
2701 * xmlSchemaGetGroup:
2702 * @schema: the context of the schema
2703 * @name: the name of the group
2704 * @ns: the target namespace of the group
2705 *
2706 * Lookup a group in the schema or imported schemas
2707 *
2708 * Returns the group definition or NULL if not found.
2709 */
2710static xmlSchemaTypePtr
2711xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2712 const xmlChar * namespace)
2713{
2714 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002715
2716 if ((name == NULL) || (schema == NULL))
2717 return (NULL);
2718
2719
2720 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2721 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2722 return (ret);
2723 else
2724 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002725 /*
2726 * Removed since imported components will be hold by the main schema only.
2727 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002728 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002729 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002730 else
2731 import = xmlHashLookup(schema->schemasImports, namespace);
2732 if (import != NULL) {
2733 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2734 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2735 return (ret);
2736 else
2737 ret = NULL;
2738 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002739 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002740#ifdef DEBUG
2741 if (ret == NULL) {
2742 if (namespace == NULL)
2743 fprintf(stderr, "Unable to lookup group %s", name);
2744 else
2745 fprintf(stderr, "Unable to lookup group %s:%s", name,
2746 namespace);
2747 }
2748#endif
2749 return (ret);
2750}
2751
Daniel Veillard4255d502002-04-16 15:50:10 +00002752/************************************************************************
2753 * *
2754 * Parsing functions *
2755 * *
2756 ************************************************************************/
2757
2758#define IS_BLANK_NODE(n) \
2759 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2760
2761/**
2762 * xmlSchemaIsBlank:
2763 * @str: a string
2764 *
2765 * Check if a string is ignorable
2766 *
2767 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2768 */
2769static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002770xmlSchemaIsBlank(xmlChar * str)
2771{
Daniel Veillard4255d502002-04-16 15:50:10 +00002772 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002773 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002774 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002775 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 return (0);
2777 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002779 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002780}
2781
2782/**
2783 * xmlSchemaAddNotation:
2784 * @ctxt: a schema validation context
2785 * @schema: the schema being built
2786 * @name: the item name
2787 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002788 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002789 * *WARNING* this interface is highly subject to change
2790 *
2791 * Returns the new struture or NULL in case of error
2792 */
2793static xmlSchemaNotationPtr
2794xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002795 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002796{
2797 xmlSchemaNotationPtr ret = NULL;
2798 int val;
2799
2800 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2801 return (NULL);
2802
2803 if (schema->notaDecl == NULL)
2804 schema->notaDecl = xmlHashCreate(10);
2805 if (schema->notaDecl == NULL)
2806 return (NULL);
2807
2808 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2809 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002810 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002811 return (NULL);
2812 }
2813 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002814 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2816 ret);
2817 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002818 /*
2819 * TODO: This should never happen, since a unique name will be computed.
2820 * If it fails, then an other internal error must have occured.
2821 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002822 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2823 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002824 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002825 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002826 xmlFree(ret);
2827 return (NULL);
2828 }
2829 return (ret);
2830}
2831
2832
2833/**
2834 * xmlSchemaAddAttribute:
2835 * @ctxt: a schema validation context
2836 * @schema: the schema being built
2837 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002838 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 *
2840 * Add an XML schema Attrribute declaration
2841 * *WARNING* this interface is highly subject to change
2842 *
2843 * Returns the new struture or NULL in case of error
2844 */
2845static xmlSchemaAttributePtr
2846xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002847 const xmlChar * name, const xmlChar * namespace,
2848 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002849{
2850 xmlSchemaAttributePtr ret = NULL;
2851 int val;
2852
2853 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2854 return (NULL);
2855
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002856#ifdef DEBUG
2857 fprintf(stderr, "Adding attribute %s\n", name);
2858 if (namespace != NULL)
2859 fprintf(stderr, " target namespace %s\n", namespace);
2860#endif
2861
Daniel Veillard4255d502002-04-16 15:50:10 +00002862 if (schema->attrDecl == NULL)
2863 schema->attrDecl = xmlHashCreate(10);
2864 if (schema->attrDecl == NULL)
2865 return (NULL);
2866
2867 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
2868 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 return (NULL);
2871 }
2872 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002873 ret->name = xmlDictLookup(ctxt->dict, name, -1);
2874 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002875 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002876 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002877 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00002878 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002879 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 NULL, NULL, node,
2881 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002882 xmlFree(ret);
2883 return (NULL);
2884 }
2885 return (ret);
2886}
2887
2888/**
2889 * xmlSchemaAddAttributeGroup:
2890 * @ctxt: a schema validation context
2891 * @schema: the schema being built
2892 * @name: the item name
2893 *
2894 * Add an XML schema Attrribute Group declaration
2895 *
2896 * Returns the new struture or NULL in case of error
2897 */
2898static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002899xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002900 xmlSchemaPtr schema, const xmlChar * name,
2901 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002902{
2903 xmlSchemaAttributeGroupPtr ret = NULL;
2904 int val;
2905
2906 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2907 return (NULL);
2908
2909 if (schema->attrgrpDecl == NULL)
2910 schema->attrgrpDecl = xmlHashCreate(10);
2911 if (schema->attrgrpDecl == NULL)
2912 return (NULL);
2913
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002914 ret =
2915 (xmlSchemaAttributeGroupPtr)
2916 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00002917 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002918 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 return (NULL);
2920 }
2921 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002922 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002923 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002924 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002925 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00002926 xmlSchemaPCustomErr(ctxt,
2927 XML_SCHEMAP_REDEFINED_ATTRGROUP,
2928 NULL, NULL, node,
2929 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 xmlFree(ret);
2931 return (NULL);
2932 }
2933 return (ret);
2934}
2935
2936/**
2937 * xmlSchemaAddElement:
2938 * @ctxt: a schema validation context
2939 * @schema: the schema being built
2940 * @name: the type name
2941 * @namespace: the type namespace
2942 *
2943 * Add an XML schema Element declaration
2944 * *WARNING* this interface is highly subject to change
2945 *
2946 * Returns the new struture or NULL in case of error
2947 */
2948static xmlSchemaElementPtr
2949xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002950 const xmlChar * name, const xmlChar * namespace,
2951 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00002952{
2953 xmlSchemaElementPtr ret = NULL;
2954 int val;
2955
2956 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2957 return (NULL);
2958
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002959#ifdef DEBUG
2960 fprintf(stderr, "Adding element %s\n", name);
2961 if (namespace != NULL)
2962 fprintf(stderr, " target namespace %s\n", namespace);
2963#endif
2964
Daniel Veillard4255d502002-04-16 15:50:10 +00002965 if (schema->elemDecl == NULL)
2966 schema->elemDecl = xmlHashCreate(10);
2967 if (schema->elemDecl == NULL)
2968 return (NULL);
2969
2970 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
2971 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002972 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002973 return (NULL);
2974 }
2975 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002976 ret->name = xmlDictLookup(ctxt->dict, name, -1);
2977 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002979 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002980 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00002981 if (topLevel) {
2982 xmlSchemaPCustomErr(ctxt,
2983 XML_SCHEMAP_REDEFINED_ELEMENT,
2984 NULL, NULL, node,
2985 "A global element declaration with the name '%s' does "
2986 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002987 xmlFree(ret);
2988 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00002989 } else {
2990 char buf[30];
2991
2992 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
2993 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
2994 namespace, ret);
2995 if (val != 0) {
2996 xmlSchemaPCustomErr(ctxt,
2997 XML_SCHEMAS_ERR_INTERNAL,
2998 NULL, NULL, node,
2999 "Internal error: xmlSchemaAddElement, "
3000 "a dublicate element declaration with the name '%s' "
3001 "could not be added to the hash.", name);
3002 xmlFree(ret);
3003 return (NULL);
3004 }
3005 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003006
Daniel Veillard4255d502002-04-16 15:50:10 +00003007 }
3008 return (ret);
3009}
3010
3011/**
3012 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003013 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003014 * @schema: the schema being built
3015 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003016 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003018 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 * *WARNING* this interface is highly subject to change
3020 *
3021 * Returns the new struture or NULL in case of error
3022 */
3023static xmlSchemaTypePtr
3024xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003025 const xmlChar * name, const xmlChar * namespace,
3026 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003027{
3028 xmlSchemaTypePtr ret = NULL;
3029 int val;
3030
3031 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3032 return (NULL);
3033
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003034#ifdef DEBUG
3035 fprintf(stderr, "Adding type %s\n", name);
3036 if (namespace != NULL)
3037 fprintf(stderr, " target namespace %s\n", namespace);
3038#endif
3039
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 if (schema->typeDecl == NULL)
3041 schema->typeDecl = xmlHashCreate(10);
3042 if (schema->typeDecl == NULL)
3043 return (NULL);
3044
3045 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3046 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003047 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003048 return (NULL);
3049 }
3050 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003051 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003052 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003053 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003054 if (val != 0) {
3055 if (ctxt->includes == 0) {
3056 xmlSchemaPCustomErr(ctxt,
3057 XML_SCHEMAP_REDEFINED_TYPE,
3058 NULL, NULL, node,
3059 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003060 xmlFree(ret);
3061 return (NULL);
3062 } else {
3063 xmlSchemaTypePtr prev;
3064
3065 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3066 if (prev == NULL) {
3067 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003068 XML_ERR_INTERNAL_ERROR,
3069 "Internal error: xmlSchemaAddType, on type "
3070 "'%s'.\n",
3071 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003072 xmlFree(ret);
3073 return (NULL);
3074 }
3075 ret->redef = prev->redef;
3076 prev->redef = ret;
3077 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003078 }
3079 ret->minOccurs = 1;
3080 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003081 ret->attributeUses = NULL;
3082 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003083
3084 return (ret);
3085}
3086
3087/**
3088 * xmlSchemaAddGroup:
3089 * @ctxt: a schema validation context
3090 * @schema: the schema being built
3091 * @name: the group name
3092 *
3093 * Add an XML schema Group definition
3094 *
3095 * Returns the new struture or NULL in case of error
3096 */
3097static xmlSchemaTypePtr
3098xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003099 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003100{
3101 xmlSchemaTypePtr ret = NULL;
3102 int val;
3103
3104 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3105 return (NULL);
3106
3107 if (schema->groupDecl == NULL)
3108 schema->groupDecl = xmlHashCreate(10);
3109 if (schema->groupDecl == NULL)
3110 return (NULL);
3111
3112 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3113 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003114 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003115 return (NULL);
3116 }
3117 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003118 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003119 val =
3120 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3121 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003122 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003123 xmlSchemaPCustomErr(ctxt,
3124 XML_SCHEMAP_REDEFINED_GROUP,
3125 NULL, NULL, node,
3126 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003127 xmlFree(ret);
3128 return (NULL);
3129 }
3130 ret->minOccurs = 1;
3131 ret->maxOccurs = 1;
3132
3133 return (ret);
3134}
3135
Daniel Veillard3646d642004-06-02 19:19:14 +00003136/**
3137 * xmlSchemaNewWildcardNs:
3138 * @ctxt: a schema validation context
3139 *
3140 * Creates a new wildcard namespace constraint.
3141 *
3142 * Returns the new struture or NULL in case of error
3143 */
3144static xmlSchemaWildcardNsPtr
3145xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3146{
3147 xmlSchemaWildcardNsPtr ret;
3148
3149 ret = (xmlSchemaWildcardNsPtr)
3150 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3151 if (ret == NULL) {
3152 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3153 return (NULL);
3154 }
3155 ret->value = NULL;
3156 ret->next = NULL;
3157 return (ret);
3158}
3159
3160/**
3161 * xmlSchemaAddWildcard:
3162 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003163 * Adds a wildcard. It corresponds to a
3164 * xsd:anyAttribute and is used as storage for namespace
3165 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003166 *
3167 * Returns the new struture or NULL in case of error
3168 */
3169static xmlSchemaWildcardPtr
3170xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3171{
3172 xmlSchemaWildcardPtr ret = NULL;
3173
3174 if (ctxt == NULL)
3175 return (NULL);
3176
3177 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3178 if (ret == NULL) {
3179 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3180 return (NULL);
3181 }
3182 memset(ret, 0, sizeof(xmlSchemaWildcard));
3183 ret->minOccurs = 1;
3184 ret->maxOccurs = 1;
3185
3186 return (ret);
3187}
3188
Daniel Veillard4255d502002-04-16 15:50:10 +00003189/************************************************************************
3190 * *
3191 * Utilities for parsing *
3192 * *
3193 ************************************************************************/
3194
3195/**
3196 * xmlGetQNameProp:
3197 * @ctxt: a schema validation context
3198 * @node: a subtree containing XML Schema informations
3199 * @name: the attribute name
3200 * @namespace: the result namespace if any
3201 *
3202 * Extract a QName Attribute value
3203 *
3204 * Returns the NCName or NULL if not found, and also update @namespace
3205 * with the namespace URI
3206 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003207static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003208xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003209 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003210{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003211 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003212 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003213 const xmlChar *ret, *prefix;
3214 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00003215
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 *namespace = NULL;
3217 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003219 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003220
Daniel Veillardba0153a2004-04-01 10:42:31 +00003221 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003222 ns = xmlSearchNs(node->doc, node, 0);
3223 if (ns) {
3224 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3225 return (val);
3226 }
3227 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003228 ret = xmlSplitQName3(val, &len);
3229 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003230 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003231 }
3232 ret = xmlDictLookup(ctxt->dict, ret, -1);
3233 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003234
3235 ns = xmlSearchNs(node->doc, node, prefix);
3236 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003237 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003238 "Attribute '%s': The prefix '%s' of the QName "
3239 "'%s' has no corresponding namespace declaration is scope.\n",
3240 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00003241 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003242 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003244 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003245}
3246
3247/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003248 * xmlSchemaPValAttrNodeQNameValue:
3249 * @ctxt: a schema parser context
3250 * @schema: the schema context
3251 * @ownerDes: the designation of the parent element
3252 * @ownerItem: the parent as a schema object
3253 * @value: the QName value
3254 * @local: the resulting local part if found, the attribute value otherwise
3255 * @uri: the resulting namespace URI if found
3256 *
3257 * Extracts the local name and the URI of a QName value and validates it.
3258 * This one is intended to be used on attribute values that
3259 * should resolve to schema components.
3260 *
3261 * Returns 0, in case the QName is valid, a positive error code
3262 * if not valid and -1 if an internal error occurs.
3263 */
3264static int
3265xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3266 xmlSchemaPtr schema,
3267 xmlChar **ownerDes,
3268 xmlSchemaTypePtr ownerItem,
3269 xmlAttrPtr attr,
3270 const xmlChar *value,
3271 const xmlChar **uri,
3272 const xmlChar **prefix,
3273 const xmlChar **local)
3274{
3275 const xmlChar *pref;
3276 xmlNsPtr ns;
3277 int len, ret;
3278
3279 *uri = NULL;
3280 *local = NULL;
3281 if (prefix != 0)
3282 *prefix = NULL;
3283 ret = xmlValidateQName(value, 1);
3284 if (ret > 0) {
3285 xmlSchemaPSimpleTypeErr(ctxt,
3286 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3287 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003288 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3289 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003290 NULL, NULL, NULL);
3291 *local = value;
3292 return (ctxt->err);
3293 } else if (ret < 0)
3294 return (-1);
3295
3296 if (!strchr((char *) value, ':')) {
3297 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3298 if (ns)
3299 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3300 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3301 /*
3302 * This one takes care of included schemas with no
3303 * target namespace.
3304 */
3305 *uri = schema->targetNamespace;
3306 }
3307 *local = value;
3308 return (0);
3309 }
3310 /*
3311 * At this point xmlSplitQName3 has to return a local name.
3312 */
3313 *local = xmlSplitQName3(value, &len);
3314 *local = xmlDictLookup(ctxt->dict, *local, -1);
3315 pref = xmlDictLookup(ctxt->dict, value, len);
3316 if (prefix != 0)
3317 *prefix = pref;
3318 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3319 if (ns == NULL) {
3320 xmlSchemaPSimpleTypeErr(ctxt,
3321 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3322 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003323 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003324 "The prefix '%s' of the value '%s' is not declared.\n",
3325 pref, value);
3326 return (ctxt->err);
3327 } else {
3328 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3329 }
3330 return (0);
3331}
3332
3333/**
3334 * xmlSchemaPValAttrNodeQName:
3335 * @ctxt: a schema parser context
3336 * @schema: the schema context
3337 * @ownerDes: the designation of the owner element
3338 * @ownerItem: the owner as a schema object
3339 * @attr: the attribute node
3340 * @local: the resulting local part if found, the attribute value otherwise
3341 * @uri: the resulting namespace URI if found
3342 *
3343 * Extracts and validates the QName of an attribute value.
3344 * This one is intended to be used on attribute values that
3345 * should resolve to schema components.
3346 *
3347 * Returns 0, in case the QName is valid, a positive error code
3348 * if not valid and -1 if an internal error occurs.
3349 */
3350static int
3351xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3352 xmlSchemaPtr schema,
3353 xmlChar **ownerDes,
3354 xmlSchemaTypePtr ownerItem,
3355 xmlAttrPtr attr,
3356 const xmlChar **uri,
3357 const xmlChar **prefix,
3358 const xmlChar **local)
3359{
3360 const xmlChar *value;
3361
3362 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3363 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3364 ownerDes, ownerItem, attr, value, uri, prefix, local));
3365}
3366
3367/**
3368 * xmlSchemaPValAttrQName:
3369 * @ctxt: a schema parser context
3370 * @schema: the schema context
3371 * @ownerDes: the designation of the parent element
3372 * @ownerItem: the owner as a schema object
3373 * @ownerElem: the parent node of the attribute
3374 * @name: the name of the attribute
3375 * @local: the resulting local part if found, the attribute value otherwise
3376 * @uri: the resulting namespace URI if found
3377 *
3378 * Extracts and validates the QName of an attribute value.
3379 *
3380 * Returns 0, in case the QName is valid, a positive error code
3381 * if not valid and -1 if an internal error occurs.
3382 */
3383static int
3384xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3385 xmlSchemaPtr schema,
3386 xmlChar **ownerDes,
3387 xmlSchemaTypePtr ownerItem,
3388 xmlNodePtr ownerElem,
3389 const char *name,
3390 const xmlChar **uri,
3391 const xmlChar **prefix,
3392 const xmlChar **local)
3393{
3394 xmlAttrPtr attr;
3395
3396 attr = xmlSchemaGetPropNode(ownerElem, name);
3397 if (attr == NULL) {
3398 *local = NULL;
3399 *uri = NULL;
3400 return (0);
3401 }
3402 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3403 ownerDes, ownerItem, attr, uri, prefix, local));
3404}
3405
3406/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003407 * xmlGetMaxOccurs:
3408 * @ctxt: a schema validation context
3409 * @node: a subtree containing XML Schema informations
3410 *
3411 * Get the maxOccurs property
3412 *
3413 * Returns the default if not found, or the value
3414 */
3415static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003416xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3417{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003418 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 int ret = 0;
3420
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003421 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003422 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003424
3425 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003426 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 }
3428
3429 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003430 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 ret = ret * 10 + (*cur - '0');
3434 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 }
William M. Brack76e95df2003-10-18 16:20:14 +00003436 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003437 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003439 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003440 "The value '%s' of the attribute 'maxOccurs' is invalid.\n",
3441 val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003442 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003444 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003445}
3446
3447/**
3448 * xmlGetMinOccurs:
3449 * @ctxt: a schema validation context
3450 * @node: a subtree containing XML Schema informations
3451 *
3452 * Get the minOccurs property
3453 *
3454 * Returns the default if not found, or the value
3455 */
3456static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3458{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003459 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003460 int ret = 0;
3461
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003462 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003463 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003464 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003465
3466 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003467 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003468 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003470 ret = ret * 10 + (*cur - '0');
3471 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003472 }
William M. Brack76e95df2003-10-18 16:20:14 +00003473 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003474 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003475 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003476 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3477 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003478 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003479 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003480 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003481}
3482
3483/**
3484 * xmlGetBooleanProp:
3485 * @ctxt: a schema validation context
3486 * @node: a subtree containing XML Schema informations
3487 * @name: the attribute name
3488 * @def: the default value
3489 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003490 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 *
3492 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003493 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 */
3495static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003496xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3497 xmlChar **ownerDes,
3498 xmlSchemaTypePtr ownerItem,
3499 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003500 const char *name, int def)
3501{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003502 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003503
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003504 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003506 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003507 /*
3508 * 3.2.2.1 Lexical representation
3509 * An instance of a datatype that is defined as ·boolean·
3510 * can have the following legal literals {true, false, 1, 0}.
3511 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003512 if (xmlStrEqual(val, BAD_CAST "true"))
3513 def = 1;
3514 else if (xmlStrEqual(val, BAD_CAST "false"))
3515 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003516 else if (xmlStrEqual(val, BAD_CAST "1"))
3517 def = 1;
3518 else if (xmlStrEqual(val, BAD_CAST "0"))
3519 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003520 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003521 xmlSchemaPSimpleTypeErr(ctxt,
3522 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003523 ownerDes, ownerItem, node,
3524 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3525 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003526 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003527 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003528}
3529
3530/************************************************************************
3531 * *
3532 * Shema extraction from an Infoset *
3533 * *
3534 ************************************************************************/
3535static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3536 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003537 xmlNodePtr node,
3538 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003539static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3540 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003542 xmlNodePtr node,
3543 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003544static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3545 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003547 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003548static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3549 xmlSchemaPtr schema,
3550 xmlNodePtr node);
3551static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3552 xmlSchemaPtr schema,
3553 xmlNodePtr node);
3554static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3555 ctxt,
3556 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003557 xmlNodePtr node,
3558 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003559static xmlSchemaAttributeGroupPtr
3560xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003561 xmlSchemaPtr schema, xmlNodePtr node,
3562 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003563static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3564 xmlSchemaPtr schema,
3565 xmlNodePtr node);
3566static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3567 xmlSchemaPtr schema,
3568 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003569static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003570xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3571 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003572
3573/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003574 * xmlSchemaPValAttrNode:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003575 *
3576 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003577 * @ownerDes: the designation of the parent element
3578 * @ownerItem: the schema object owner if existent
3579 * @attr: the schema attribute node being validated
3580 * @value: the value
3581 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003582 *
3583 * Validates a value against the given built-in type.
3584 * This one is intended to be used internally for validation
3585 * of schema attribute values during parsing of the schema.
3586 *
3587 * Returns 0 if the value is valid, a positive error code
3588 * number otherwise and -1 in case of an internal or API error.
3589 */
3590static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003591xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3592 xmlChar **ownerDes,
3593 xmlSchemaTypePtr ownerItem,
3594 xmlAttrPtr attr,
3595 const xmlChar *value,
3596 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003597{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003598
Daniel Veillardc0826a72004-08-10 14:17:33 +00003599 int ret = 0;
3600
3601 /*
3602 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3603 * one is really meant to be used internally, so better not.
3604 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003605 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003606 return (-1);
3607 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3608 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3609 XML_SCHEMAS_ERR_INTERNAL,
3610 "Internal error: xmlSchemaPvalueAttrNode, the given "
3611 "type '%s' is not a built-in type.\n",
3612 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003613 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003614 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003615 switch (type->builtInType) {
3616 case XML_SCHEMAS_NCNAME:
3617 ret = xmlValidateNCName(value, 1);
3618 break;
3619 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003620 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3621 XML_SCHEMAS_ERR_INTERNAL,
3622 "Internal error: xmlSchemaPvalueAttrNode, use "
3623 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3624 "for extracting QName valueues instead.\n",
3625 NULL, NULL);
3626 return (-1);
3627 case XML_SCHEMAS_ANYURI:
3628 if (value != NULL) {
3629 xmlURIPtr uri = xmlParseURI((const char *) value);
3630 if (uri == NULL)
3631 ret = 1;
3632 else
3633 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003634 }
3635 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003636 case XML_SCHEMAS_TOKEN: {
3637 const xmlChar *cur = value;
3638
3639 if (IS_BLANK_CH(*cur)) {
3640 ret = 1;
3641 } else while (*cur != 0) {
3642 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3643 ret = 1;
3644 break;
3645 } else if (*cur == ' ') {
3646 cur++;
3647 if ((*cur == 0) || (*cur == ' ')) {
3648 ret = 1;
3649 break;
3650 }
3651 } else {
3652 cur++;
3653 }
3654 }
3655 }
3656 break;
3657 case XML_SCHEMAS_LANGUAGE:
3658 if (xmlCheckLanguageID(value) != 1)
3659 ret = 1;
3660 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003661 default: {
3662 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3663 XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003664 "Internal error: xmlSchemaPvalueAttrNode, "
3665 "valueidation using the type '%s' is not implemented "
3666 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003667 type->name, NULL);
3668 return (-1);
3669 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003670 }
3671 /*
3672 * TODO: Should we use the S4S error codes instead?
3673 */
3674 if (ret > 0) {
3675 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3676 xmlSchemaPSimpleTypeErr(ctxt,
3677 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3678 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003679 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003680 NULL, NULL, NULL);
3681 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3682 } else {
3683 xmlSchemaPSimpleTypeErr(ctxt,
3684 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3685 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003686 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003687 NULL, NULL, NULL);
3688 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3689 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003690 }
3691 return (ret);
3692}
3693
3694/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003695 * xmlSchemaPValAttrNode:
3696 *
3697 * @ctxt: a schema parser context
3698 * @ownerDes: the designation of the parent element
3699 * @ownerItem: the schema object owner if existent
3700 * @attr: the schema attribute node being validated
3701 * @type: the built-in type to be validated against
3702 * @value: the resulting value if any
3703 *
3704 * Extracts and validates a value against the given built-in type.
3705 * This one is intended to be used internally for validation
3706 * of schema attribute values during parsing of the schema.
3707 *
3708 * Returns 0 if the value is valid, a positive error code
3709 * number otherwise and -1 in case of an internal or API error.
3710 */
3711static int
3712xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3713 xmlChar **ownerDes,
3714 xmlSchemaTypePtr ownerItem,
3715 xmlAttrPtr attr,
3716 xmlSchemaTypePtr type,
3717 const xmlChar **value)
3718{
3719 const xmlChar *val;
3720
3721 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3722 return (-1);
3723
3724 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3725 if (value != NULL)
3726 *value = val;
3727
3728 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3729 val, type));
3730}
3731
3732/**
3733 * xmlSchemaPValAttr:
3734 *
3735 * @ctxt: a schema parser context
3736 * @node: the element node of the attribute
3737 * @ownerDes: the designation of the parent element
3738 * @ownerItem: the schema object owner if existent
3739 * @ownerElem: the owner element node
3740 * @name: the name of the schema attribute node
3741 * @type: the built-in type to be validated against
3742 * @value: the resulting value if any
3743 *
3744 * Extracts and validates a value against the given built-in type.
3745 * This one is intended to be used internally for validation
3746 * of schema attribute values during parsing of the schema.
3747 *
3748 * Returns 0 if the value is valid, a positive error code
3749 * number otherwise and -1 in case of an internal or API error.
3750 */
3751static int
3752xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3753 xmlChar **ownerDes,
3754 xmlSchemaTypePtr ownerItem,
3755 xmlNodePtr ownerElem,
3756 const char *name,
3757 xmlSchemaTypePtr type,
3758 const xmlChar **value)
3759{
3760 xmlAttrPtr attr;
3761
3762 if ((ctxt == NULL) || (type == NULL)) {
3763 if (value != NULL)
3764 *value = NULL;
3765 return (-1);
3766 }
3767 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3768 if (value != NULL)
3769 *value = NULL;
3770 xmlSchemaPErr(ctxt, ownerElem,
3771 XML_SCHEMAS_ERR_INTERNAL,
3772 "Internal error: xmlSchemaPValAttr, the given "
3773 "type '%s' is not a built-in type.\n",
3774 type->name, NULL);
3775 return (-1);
3776 }
3777 attr = xmlSchemaGetPropNode(ownerElem, name);
3778 if (attr == NULL) {
3779 if (value != NULL)
3780 *value = NULL;
3781 return (0);
3782 }
3783 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
3784 type, value));
3785}
3786/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003787 * xmlSchemaParseAttrDecls:
3788 * @ctxt: a schema validation context
3789 * @schema: the schema being built
3790 * @node: a subtree containing XML Schema informations
3791 * @type: the hosting type
3792 *
3793 * parse a XML schema attrDecls declaration corresponding to
3794 * <!ENTITY % attrDecls
3795 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
3796 */
3797static xmlNodePtr
3798xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3799 xmlNodePtr child, xmlSchemaTypePtr type)
3800{
3801 xmlSchemaAttributePtr lastattr, attr;
3802
3803 lastattr = NULL;
3804 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003805 (IS_SCHEMA(child, "attributeGroup"))) {
3806 attr = NULL;
3807 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003808 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003809 } else if (IS_SCHEMA(child, "attributeGroup")) {
3810 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003811 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003812 }
3813 if (attr != NULL) {
3814 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003815 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3816 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
3817 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003818 type->attributes = attr;
3819 lastattr = attr;
3820 } else {
3821 lastattr->next = attr;
3822 lastattr = attr;
3823 }
3824 }
3825 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003826 }
3827 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003828 xmlSchemaWildcardPtr wildcard;
3829
3830 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
3831 if (wildcard != NULL) {
3832 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3833 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
3834 else
3835 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003836 }
3837 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003838 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003839 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00003840}
3841
3842/**
3843 * xmlSchemaParseAnnotation:
3844 * @ctxt: a schema validation context
3845 * @schema: the schema being built
3846 * @node: a subtree containing XML Schema informations
3847 *
3848 * parse a XML schema Attrribute declaration
3849 * *WARNING* this interface is highly subject to change
3850 *
William M. Bracke7091952004-05-11 15:09:58 +00003851 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003852 * 1 in case of success.
3853 */
3854static xmlSchemaAnnotPtr
3855xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3856 xmlNodePtr node)
3857{
3858 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003859 xmlNodePtr child = NULL;
3860 xmlAttrPtr attr;
3861 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003862
Daniel Veillardc0826a72004-08-10 14:17:33 +00003863 /*
3864 * INFO: S4S completed.
3865 */
3866 /*
3867 * id = ID
3868 * {any attributes with non-schema namespace . . .}>
3869 * Content: (appinfo | documentation)*
3870 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3872 return (NULL);
3873 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003874 attr = node->properties;
3875 while (attr != NULL) {
3876 if (((attr->ns == NULL) &&
3877 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
3878 ((attr->ns != NULL) &&
3879 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
3880
3881 xmlSchemaPIllegalAttrErr(ctxt,
3882 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3883 NULL, NULL, attr);
3884 }
3885 attr = attr->next;
3886 }
3887 /* TODO: Check id. */
3888
3889 /*
3890 * And now for the children...
3891 */
3892 child = node->children;
3893 while (child != NULL) {
3894 if (IS_SCHEMA(child, "appinfo")) {
3895 /* TODO: make available the content of "appinfo". */
3896 /*
3897 * source = anyURI
3898 * {any attributes with non-schema namespace . . .}>
3899 * Content: ({any})*
3900 */
3901 attr = child->properties;
3902 while (attr != NULL) {
3903 if (((attr->ns == NULL) &&
3904 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
3905 ((attr->ns != NULL) &&
3906 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003907
Daniel Veillardc0826a72004-08-10 14:17:33 +00003908 xmlSchemaPIllegalAttrErr(ctxt,
3909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3910 NULL, NULL, attr);
3911 }
3912 attr = attr->next;
3913 }
3914 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
3915 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
3916 child = child->next;
3917 } else if (IS_SCHEMA(child, "documentation")) {
3918 /* TODO: make available the content of "documentation". */
3919 /*
3920 * source = anyURI
3921 * {any attributes with non-schema namespace . . .}>
3922 * Content: ({any})*
3923 */
3924 attr = child->properties;
3925 while (attr != NULL) {
3926 if (attr->ns == NULL) {
3927 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
3928 xmlSchemaPIllegalAttrErr(ctxt,
3929 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3930 NULL, NULL, attr);
3931 }
3932 } else {
3933 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
3934 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
3935 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
3936
3937 xmlSchemaPIllegalAttrErr(ctxt,
3938 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3939 NULL, NULL, attr);
3940 }
3941 }
3942 attr = attr->next;
3943 }
3944 /*
3945 * Attribute "xml:lang".
3946 */
3947 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
3948 if (attr != NULL)
3949 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
3950 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
3951 child = child->next;
3952 } else {
3953 if (!barked)
3954 xmlSchemaPContentErr(ctxt,
3955 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3956 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
3957 barked = 1;
3958 child = child->next;
3959 }
3960 }
3961
Daniel Veillard4255d502002-04-16 15:50:10 +00003962 return (ret);
3963}
3964
3965/**
3966 * xmlSchemaParseFacet:
3967 * @ctxt: a schema validation context
3968 * @schema: the schema being built
3969 * @node: a subtree containing XML Schema informations
3970 *
3971 * parse a XML schema Facet declaration
3972 * *WARNING* this interface is highly subject to change
3973 *
3974 * Returns the new type structure or NULL in case of error
3975 */
3976static xmlSchemaFacetPtr
3977xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003978 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003979{
3980 xmlSchemaFacetPtr facet;
3981 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003982 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00003983
3984 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3985 return (NULL);
3986
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003987 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003988 if (facet == NULL) {
3989 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
3990 return (NULL);
3991 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003992 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003993 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00003994 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003995 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
3996 "Facet %s has no value\n", node->name, NULL);
3997 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00003998 return (NULL);
3999 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004000 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004001 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004002 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004003 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004004 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004005 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004006 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004007 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004008 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004009 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004010 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004011 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004012 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004013 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004014 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004015 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004016 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004017 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004018 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004019 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004020 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004021 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4022 } else if (IS_SCHEMA(node, "minLength")) {
4023 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4024 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004025 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4026 "Unknown facet type %s\n", node->name, NULL);
4027 xmlSchemaFreeFacet(facet);
4028 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004029 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004030 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004031 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004032 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4033 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4034 const xmlChar *fixed;
4035
4036 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4037 if (fixed != NULL) {
4038 if (xmlStrEqual(fixed, BAD_CAST "true"))
4039 facet->fixed = 1;
4040 }
4041 }
4042
Daniel Veillard4255d502002-04-16 15:50:10 +00004043 child = node->children;
4044
4045 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004046 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4047 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004048 }
4049 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004050 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4051 "Facet %s has unexpected child content\n",
4052 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004053 }
4054 return (facet);
4055}
4056
4057/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004058 * xmlSchemaParseWildcardNs:
4059 * @ctxt: a schema parser context
4060 * @wildc: the wildcard, already created
4061 * @node: a subtree containing XML Schema informations
4062 *
4063 * Parses the attribute "processContents" and "namespace"
4064 * of a xsd:anyAttribute and xsd:any.
4065 * *WARNING* this interface is highly subject to change
4066 *
4067 * Returns 0 if everything goes fine, a positive error code
4068 * if something is not valid and -1 if an internal error occurs.
4069 */
4070static int
4071xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4072 xmlSchemaPtr schema,
4073 xmlSchemaWildcardPtr wildc,
4074 xmlNodePtr node)
4075{
4076 const xmlChar *pc, *ns, *dictnsItem;
4077 int ret = 0;
4078 xmlChar *nsItem;
4079 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4080 xmlAttrPtr attr;
4081
4082 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4083 if ((pc == NULL)
4084 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4085 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4086 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4087 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4088 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4089 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4090 } else {
4091 xmlSchemaPSimpleTypeErr(ctxt,
4092 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4093 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004094 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004095 NULL, NULL, NULL);
4096 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4097 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4098 }
4099 /*
4100 * Build the namespace constraints.
4101 */
4102 attr = xmlSchemaGetPropNode(node, "namespace");
4103 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4104 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4105 wildc->any = 1;
4106 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4107 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4108 if (wildc->negNsSet == NULL) {
4109 return (-1);
4110 }
4111 wildc->negNsSet->value = schema->targetNamespace;
4112 } else {
4113 const xmlChar *end, *cur;
4114
4115 cur = ns;
4116 do {
4117 while (IS_BLANK_CH(*cur))
4118 cur++;
4119 end = cur;
4120 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4121 end++;
4122 if (end == cur)
4123 break;
4124 nsItem = xmlStrndup(cur, end - cur);
4125 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4126 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4127 xmlSchemaPSimpleTypeErr(ctxt,
4128 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4129 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004130 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004131 "((##any | ##other) | List of (anyURI | "
4132 "(##targetNamespace | ##local)))",
4133 nsItem, NULL, NULL, NULL);
4134 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4135 } else {
4136 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4137 dictnsItem = schema->targetNamespace;
4138 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4139 dictnsItem = NULL;
4140 } else {
4141 /*
4142 * Validate the item (anyURI).
4143 */
4144 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4145 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4146 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4147 }
4148 /*
4149 * Avoid dublicate namespaces.
4150 */
4151 tmp = wildc->nsSet;
4152 while (tmp != NULL) {
4153 if (dictnsItem == tmp->value)
4154 break;
4155 tmp = tmp->next;
4156 }
4157 if (tmp == NULL) {
4158 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4159 if (tmp == NULL) {
4160 xmlFree(nsItem);
4161 return (-1);
4162 }
4163 tmp->value = dictnsItem;
4164 tmp->next = NULL;
4165 if (wildc->nsSet == NULL)
4166 wildc->nsSet = tmp;
4167 else
4168 lastNs->next = tmp;
4169 lastNs = tmp;
4170 }
4171
4172 }
4173 xmlFree(nsItem);
4174 cur = end;
4175 } while (*cur != 0);
4176 }
4177 return (ret);
4178}
4179/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004180 * xmlSchemaParseAny:
4181 * @ctxt: a schema validation context
4182 * @schema: the schema being built
4183 * @node: a subtree containing XML Schema informations
4184 *
4185 * parse a XML schema Any declaration
4186 * *WARNING* this interface is highly subject to change
4187 *
4188 * Returns the new type structure or NULL in case of error
4189 */
4190static xmlSchemaTypePtr
4191xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4192 xmlNodePtr node)
4193{
4194 xmlSchemaTypePtr type;
4195 xmlNodePtr child = NULL;
4196 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004197 xmlSchemaWildcardPtr wildc;
Daniel Veillard4255d502002-04-16 15:50:10 +00004198
4199 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4200 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004201 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004202 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004203 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004204 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004205 type->node = node;
4206 type->type = XML_SCHEMA_TYPE_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4208 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004209 wildc = xmlSchemaAddWildcard(ctxt);
4210 /*
4211 * This is not nice, since it is won't be used as a attribute wildcard,
4212 * but better than adding a field to the structure.
4213 */
4214 type->attributeWildcard = wildc;
4215 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
4216 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 }
4221 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004222 xmlSchemaPErr2(ctxt, node, child,
4223 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4224 "Sequence %s has unexpected content\n", type->name,
4225 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004226 }
4227
4228 return (type);
4229}
4230
4231/**
4232 * xmlSchemaParseNotation:
4233 * @ctxt: a schema validation context
4234 * @schema: the schema being built
4235 * @node: a subtree containing XML Schema informations
4236 *
4237 * parse a XML schema Notation declaration
4238 *
4239 * Returns the new structure or NULL in case of error
4240 */
4241static xmlSchemaNotationPtr
4242xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004243 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004244{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004245 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 xmlSchemaNotationPtr ret;
4247 xmlNodePtr child = NULL;
4248
4249 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4250 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004251 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004252 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4254 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 return (NULL);
4256 }
4257 ret = xmlSchemaAddNotation(ctxt, schema, name);
4258 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004259 return (NULL);
4260 }
4261 child = node->children;
4262 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004263 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4264 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004265 }
4266 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004267 xmlSchemaPErr2(ctxt, node, child,
4268 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4269 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 }
4271
4272 return (ret);
4273}
4274
4275/**
4276 * xmlSchemaParseAnyAttribute:
4277 * @ctxt: a schema validation context
4278 * @schema: the schema being built
4279 * @node: a subtree containing XML Schema informations
4280 *
4281 * parse a XML schema AnyAttrribute declaration
4282 * *WARNING* this interface is highly subject to change
4283 *
4284 * Returns an attribute def structure or NULL
4285 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004286static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004287xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4288 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004289{
Daniel Veillard3646d642004-06-02 19:19:14 +00004290 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004292
4293 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4294 return (NULL);
4295
Daniel Veillard3646d642004-06-02 19:19:14 +00004296 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 if (ret == NULL) {
4298 return (NULL);
4299 }
William M. Bracke7091952004-05-11 15:09:58 +00004300 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004301 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004302 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4303 xmlSchemaFreeWildcard(ret);
4304 return (NULL);
4305 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004306 child = node->children;
4307 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004308 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4309 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004310 }
4311 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004312 /* TODO: Change the error code. */
4313 xmlSchemaPContentErr(ctxt,
4314 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
4315 NULL, NULL, node, child,
4316 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 }
4318
4319 return (ret);
4320}
4321
4322
4323/**
4324 * xmlSchemaParseAttribute:
4325 * @ctxt: a schema validation context
4326 * @schema: the schema being built
4327 * @node: a subtree containing XML Schema informations
4328 *
4329 * parse a XML schema Attrribute declaration
4330 * *WARNING* this interface is highly subject to change
4331 *
William M. Bracke7091952004-05-11 15:09:58 +00004332 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 */
4334static xmlSchemaAttributePtr
4335xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004336 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004337{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004338 const xmlChar *name, *attrValue;
4339 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004340 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004341 xmlNodePtr child = NULL;
4342 xmlAttrPtr attr, nameAttr;
4343 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004344
4345 /*
4346 * Note that the w3c spec assumes the schema to be validated with schema
4347 * for schemas beforehand.
4348 *
4349 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004350 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004351
4352 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4353 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004354 attr = xmlSchemaGetPropNode(node, "ref");
4355 nameAttr = xmlSchemaGetPropNode(node, "name");
4356
4357 if ((attr == NULL) && (nameAttr == NULL)) {
4358 /*
4359 * 3.2.3 : 3.1
4360 * One of ref or name must be present, but not both
4361 */
4362 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4363 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4364 "One of the attributes 'ref' or 'name' must be present");
4365 return (NULL);
4366 }
4367 if ((topLevel) || (attr == NULL)) {
4368 if (nameAttr == NULL) {
4369 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4370 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4371 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004372 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004373 }
4374 } else
4375 isRef = 1;
4376
4377 if (isRef) {
4378 char buf[100];
4379 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4380
4381 /*
4382 * Parse as attribute reference.
4383 */
4384 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4385 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4386 &refPrefix, &ref) != 0) {
4387 return (NULL);
4388 }
4389 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4390 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004391 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004392 if (ret == NULL) {
4393 if (repName != NULL)
4394 xmlFree(repName);
4395 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004396 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004397 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4398 ret->node = node;
4399 ret->refNs = refNs;
4400 ret->refPrefix = refPrefix;
4401 ret->ref = ref;
4402 /*
4403 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4404 */
4405 if (nameAttr != NULL)
4406 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4407 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4408 "ref", "name");
4409 /*
4410 * Check for illegal attributes.
4411 */
4412 attr = node->properties;
4413 while (attr != NULL) {
4414 if (attr->ns == NULL) {
4415 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4416 xmlStrEqual(attr->name, BAD_CAST "form")) {
4417 /*
4418 * 3.2.3 : 3.2
4419 * If ref is present, then all of <simpleType>,
4420 * form and type must be absent.
4421 */
4422 xmlSchemaPIllegalAttrErr(ctxt,
4423 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4424 (xmlSchemaTypePtr) ret, attr);
4425 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4426 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4427 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4428 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4429 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4430 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4431 xmlSchemaPIllegalAttrErr(ctxt,
4432 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4433 &repName, (xmlSchemaTypePtr) ret, attr);
4434 }
4435 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4436 xmlSchemaPIllegalAttrErr(ctxt,
4437 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4438 &repName, (xmlSchemaTypePtr) ret, attr);
4439 }
4440 attr = attr->next;
4441 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004442 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004443 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004444
4445 /*
4446 * Parse as attribute declaration.
4447 */
4448 if (xmlSchemaPValAttrNode(ctxt,
4449 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4450 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4451 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004452 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004453 /*
4454 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4455 */
4456 /*
4457 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4458 */
4459 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4460 xmlSchemaPSimpleTypeErr(ctxt,
4461 XML_SCHEMAP_NO_XMLNS,
4462 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004463 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004464 "The value must not match 'xmlns'",
4465 NULL, NULL);
4466 if (repName != NULL)
4467 xmlFree(repName);
4468 return (NULL);
4469 }
4470 /*
4471 * Evaluate the target namespace
4472 */
William M. Bracke7091952004-05-11 15:09:58 +00004473 if (schema->targetNamespace != NULL) {
4474 if (topLevel) {
4475 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004476 } else {
4477 attr = xmlSchemaGetPropNode(node, "form");
4478 if (attr != NULL) {
4479 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4480 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4481 ns = schema->targetNamespace;
4482 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4483 xmlSchemaPSimpleTypeErr(ctxt,
4484 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4485 &repName, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004486 NULL, "(qualified | unqualified)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004487 attrValue, NULL, NULL, NULL);
4488 }
4489 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4490 ns = schema->targetNamespace;
4491 }
4492 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004493 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004494 if (ret == NULL) {
4495 if (repName != NULL)
4496 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004497 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004498 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004499 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4500 ret->node = node;
4501 if (topLevel)
4502 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4503 /*
4504 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4505 */
4506 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4507 xmlSchemaPCustomErr(ctxt,
4508 XML_SCHEMAP_NO_XSI,
4509 &repName, (xmlSchemaTypePtr) ret, node,
4510 "The target namespace must not match '%s'",
4511 xmlSchemaInstanceNs);
4512 }
4513 /*
4514 * Check for illegal attributes.
4515 */
4516 attr = node->properties;
4517 while (attr != NULL) {
4518 if (attr->ns == NULL) {
4519 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4520 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4521 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4522 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4523 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4524 if ((topLevel) ||
4525 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4526 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4527 xmlSchemaPIllegalAttrErr(ctxt,
4528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4529 &repName, (xmlSchemaTypePtr) ret, attr);
4530 }
4531 }
4532 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4533 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4534 &repName, (xmlSchemaTypePtr) ret, attr);
4535 }
4536 attr = attr->next;
4537 }
4538 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4539 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004540 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004541 /* TODO: Check ID. */
4542 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004543 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004544 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004545 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004546 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4547 if (ret->defValue != NULL)
4548 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4549 /*
4550 * Attribute "default".
4551 */
4552 attr = xmlSchemaGetPropNode(node, "default");
4553 if (attr != NULL) {
4554 /*
4555 * 3.2.3 : 1
4556 * default and fixed must not both be present.
4557 */
4558 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4559 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4560 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4561 } else
4562 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4563 }
4564 if (topLevel == 0) {
4565 /*
4566 * Attribute "use".
4567 */
4568 attr = xmlSchemaGetPropNode(node, "use");
4569 if (attr != NULL) {
4570 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4571 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4572 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4573 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4574 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4575 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4576 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4577 else
4578 xmlSchemaPSimpleTypeErr(ctxt,
4579 XML_SCHEMAP_INVALID_ATTR_USE,
4580 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004581 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004582 attrValue, NULL, NULL, NULL);
4583 } else
4584 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4585 /*
4586 * 3.2.3 : 2
4587 * If default and use are both present, use must have
4588 * the actual value optional.
4589 */
4590 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4591 (ret->defValue != NULL) &&
4592 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4593 xmlSchemaPSimpleTypeErr(ctxt,
4594 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4595 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004596 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 "The value must be 'optional' if the attribute "
4598 "'default' is present as well", NULL, NULL);
4599 }
4600 }
4601 /*
4602 * And now for the children...
4603 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004604 child = node->children;
4605 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004606 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4607 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004608 }
4609 if (isRef) {
4610 if (child != NULL) {
4611 if (IS_SCHEMA(child, "simpleType"))
4612 /*
4613 * 3.2.3 : 3.2
4614 * If ref is present, then all of <simpleType>,
4615 * form and type must be absent.
4616 */
4617 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4618 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4619 "(annotation?)");
4620 else
4621 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4622 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4623 "(annotation?)");
4624 }
4625 } else {
4626 if (IS_SCHEMA(child, "simpleType")) {
4627 if (ret->typeName != NULL) {
4628 /*
4629 * 3.2.3 : 4
4630 * type and <simpleType> must not both be present.
4631 */
4632 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4633 &repName, (xmlSchemaTypePtr) ret, node, child,
4634 "The attribute 'type' and the <simpleType> child "
4635 "are mutually exclusive", NULL);
4636 } else
4637 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4638 child = child->next;
4639 }
4640 if (child != NULL)
4641 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4642 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4643 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004645 /*
4646 * Cleanup.
4647 */
4648 if (repName != NULL)
4649 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004650 return (ret);
4651}
4652
4653/**
4654 * xmlSchemaParseAttributeGroup:
4655 * @ctxt: a schema validation context
4656 * @schema: the schema being built
4657 * @node: a subtree containing XML Schema informations
4658 *
4659 * parse a XML schema Attribute Group declaration
4660 * *WARNING* this interface is highly subject to change
4661 *
4662 * Returns the attribute group or NULL in case of error.
4663 */
4664static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004665xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004666 xmlSchemaPtr schema, xmlNodePtr node,
4667 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004668{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004669 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004671 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004672 const xmlChar *oldcontainer;
4673 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004674
4675 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4676 return (NULL);
4677 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004678 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004679 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004680 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
4681 if (ref == NULL) {
4682 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004683 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
4684 "Attribute group or particle: One of the attributes 'name' "
4685 "or 'ref' must be present.\n", NULL,
4686 NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004687 return (NULL);
4688 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004689 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
4690 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004691 if (name == NULL) {
4692 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
4693 return (NULL);
4694 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004695 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004696 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004697 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004698 return (NULL);
4699 }
4700 ret->ref = ref;
4701 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004702 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00004703 if (topLevel)
4704 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004705 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 child = node->children;
4707 ctxt->container = name;
4708 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004709 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4710 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004711 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004712 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004713 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004714 xmlSchemaPErr2(ctxt, node, child,
4715 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004716 "Attribute group '%s' has unexpected content.\n", name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004717 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004718 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004719 ctxt->container = oldcontainer;
4720 return (ret);
4721}
4722
4723/**
William M. Brack2f2a6632004-08-20 23:09:47 +00004724 * xmlSchemaPValAttrFormDefault:
4725 * @value: the value
4726 * @flags: the flags to be modified
4727 * @flagQualified: the specific flag for "qualified"
4728 *
4729 * Returns 0 if the value is valid, 1 otherwise.
4730 */
4731static int
4732xmlSchemaPValAttrFormDefault(const xmlChar *value,
4733 int *flags,
4734 int flagQualified)
4735{
4736 if (xmlStrEqual(value, BAD_CAST "qualified")) {
4737 if ((*flags & flagQualified) == 0)
4738 *flags |= flagQualified;
4739 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
4740 return (1);
4741
4742 return (0);
4743}
4744
4745/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004746 * xmlSchemaPValAttrBlockFinal:
4747 * @value: the value
4748 * @flags: the flags to be modified
4749 * @flagAll: the specific flag for "#all"
4750 * @flagExtension: the specific flag for "extension"
4751 * @flagRestriction: the specific flag for "restriction"
4752 * @flagSubstitution: the specific flag for "substitution"
4753 * @flagList: the specific flag for "list"
4754 * @flagUnion: the specific flag for "union"
4755 *
4756 * Validates the value of the attribute "final" and "block". The value
4757 * is converted into the specified flag values and returned in @flags.
4758 *
4759 * Returns 0 if the value is valid, 1 otherwise.
4760 */
4761
4762static int
4763xmlSchemaPValAttrBlockFinal(const xmlChar *value,
4764 int *flags,
4765 int flagAll,
4766 int flagExtension,
4767 int flagRestriction,
4768 int flagSubstitution,
4769 int flagList,
4770 int flagUnion)
4771{
4772 int ret = 0;
4773
4774 /*
4775 * TODO: This does not check for dublicate entries.
4776 */
William M. Brack2f2a6632004-08-20 23:09:47 +00004777 if (value == NULL)
4778 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004779 if (xmlStrEqual(value, BAD_CAST "#all")) {
4780 if (flagAll != -1)
4781 *flags |= flagAll;
4782 else {
4783 if (flagExtension != -1)
4784 *flags |= flagExtension;
4785 if (flagRestriction != -1)
4786 *flags |= flagRestriction;
4787 if (flagSubstitution != -1)
4788 *flags |= flagSubstitution;
4789 if (flagList != -1)
4790 *flags |= flagList;
4791 if (flagUnion != -1)
4792 *flags |= flagUnion;
4793 }
4794 } else {
4795 const xmlChar *end, *cur = value;
4796 xmlChar *item;
4797
4798 do {
4799 while (IS_BLANK_CH(*cur))
4800 cur++;
4801 end = cur;
4802 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4803 end++;
4804 if (end == cur)
4805 break;
4806 item = xmlStrndup(cur, end - cur);
4807 if (xmlStrEqual(item, BAD_CAST "extension")) {
4808 if (flagExtension != -1) {
4809 if ((*flags & flagExtension) == 0)
4810 *flags |= flagExtension;
4811 } else
4812 ret = 1;
4813 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4814 if (flagRestriction != -1) {
4815 if ((*flags & flagRestriction) == 0)
4816 *flags |= flagRestriction;
4817 } else
4818 ret = 1;
4819 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
4820 if (flagSubstitution != -1) {
4821 if ((*flags & flagSubstitution) == 0)
4822 *flags |= flagSubstitution;
4823 } else
4824 ret = 1;
4825 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4826 if (flagList != -1) {
4827 if ((*flags & flagList) == 0)
4828 *flags |= flagList;
4829 } else
4830 ret = 1;
4831 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4832 if (flagUnion != -1) {
4833 if ((*flags & flagUnion) == 0)
4834 *flags |= flagUnion;
4835 } else
4836 ret = 1;
4837 } else
4838 ret = 1;
4839 if (item != NULL)
4840 xmlFree(item);
4841 cur = end;
4842 } while ((ret == 0) && (*cur != 0));
4843 }
4844
4845 return (ret);
4846}
4847
4848/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004849 * xmlSchemaParseElement:
4850 * @ctxt: a schema validation context
4851 * @schema: the schema being built
4852 * @node: a subtree containing XML Schema informations
4853 *
4854 * parse a XML schema Element declaration
4855 * *WARNING* this interface is highly subject to change
4856 *
William M. Bracke7091952004-05-11 15:09:58 +00004857 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004858 */
4859static xmlSchemaElementPtr
4860xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004861 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004862{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004863 const xmlChar *name = NULL;
4864 const xmlChar *attrValue;
4865 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004866 xmlSchemaElementPtr ret;
4867 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004868 const xmlChar *oldcontainer;
4869 xmlAttrPtr attr, nameAttr;
4870 int minOccurs, maxOccurs;
4871 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004872
4873 /* 3.3.3 Constraints on XML Representations of Element Declarations */
4874 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004875
Daniel Veillard4255d502002-04-16 15:50:10 +00004876 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4877 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004878
Daniel Veillardc0826a72004-08-10 14:17:33 +00004879 oldcontainer = ctxt->container;
4880
4881 nameAttr = xmlSchemaGetPropNode(node, "name");
4882 attr = xmlSchemaGetPropNode(node, "ref");
4883 if ((topLevel) || (attr == NULL)) {
4884 if (nameAttr == NULL) {
4885 xmlSchemaPMissingAttrErr(ctxt,
4886 XML_SCHEMAP_S4S_ATTR_MISSING,
4887 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
4888 "name", NULL);
4889 return (NULL);
4890 }
4891 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
4892 } else {
4893 isRef = 1;
4894
4895 }
4896 /*
4897 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
4898 * to no component at all
4899 * TODO: It might be better to validate the element, even if it won't be
4900 * used.
4901 */
4902 minOccurs = xmlGetMinOccurs(ctxt, node);
4903 maxOccurs = xmlGetMaxOccurs(ctxt, node);
4904 if ((minOccurs == 0) && (maxOccurs == 0))
4905 return (NULL);
4906 /*
4907 * If we get a "ref" attribute on a local <element> we will assume it's
4908 * a reference - even if there's a "name" attribute; this seems to be more
4909 * robust.
4910 */
4911 if (isRef) {
4912 char buf[100];
4913 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
4914
4915 /*
4916 * Parse as a particle.
4917 */
4918 xmlSchemaPValAttrNodeQName(ctxt, schema,
4919 (xmlChar **) &xmlSchemaElemDesAttrRef,
4920 NULL, attr, &refNs, &refPrefix, &ref);
4921
4922 snprintf(buf, 99, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004923 name = (const xmlChar *) buf;
4924 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004925 if (ret == NULL) {
4926 if (repName != NULL)
4927 xmlFree(repName);
4928 return (NULL);
4929 }
4930 ret->type = XML_SCHEMA_TYPE_ELEMENT;
4931 ret->node = node;
4932 ret->ref = ref;
4933 ret->refNs = refNs;
4934 ret->refPrefix = refPrefix;
4935 ret->flags |= XML_SCHEMAS_ELEM_REF;
4936 /*
4937 * Check for illegal attributes.
4938 */
4939 /*
4940 * 3.3.3 : 2.1
4941 * One of ref or name must be present, but not both
4942 */
4943 if (nameAttr != NULL) {
4944 xmlSchemaPMutualExclAttrErr(ctxt,
4945 XML_SCHEMAP_SRC_ELEMENT_2_1,
4946 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4947 "ref", "name");
4948 }
4949 /* 3.3.3 : 2.2 */
4950 attr = node->properties;
4951 while (attr != NULL) {
4952 if (attr->ns == NULL) {
4953 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4954 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4955 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
4956 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
4957 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
4958 xmlSchemaPCustomAttrErr(ctxt,
4959 XML_SCHEMAP_SRC_ELEMENT_2_2,
4960 &repName, (xmlSchemaTypePtr) ret, attr,
4961 "Only the attributes 'minOccurs', 'maxOccurs' and "
4962 "'id' are allowed in addition to 'ref'");
4963 break;
4964 }
4965 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4966 xmlSchemaPIllegalAttrErr(ctxt,
4967 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4968 &repName, (xmlSchemaTypePtr) ret, attr);
4969 }
4970 attr = attr->next;
4971 }
4972 } else {
4973 const xmlChar *ns = NULL, *fixed;
4974
4975 /*
4976 * Parse as an element declaration.
4977 */
4978 if (xmlSchemaPValAttrNode(ctxt,
4979 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
4980 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
4981 return (NULL);
4982 /*
4983 * Evaluate the target namespace.
4984 */
William M. Bracke7091952004-05-11 15:09:58 +00004985 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004986 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00004987 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004988 } else {
4989 attr = xmlSchemaGetPropNode(node, "form");
4990 if (attr != NULL) {
4991 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4992 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4993 ns = schema->targetNamespace;
4994 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4995 xmlSchemaPSimpleTypeErr(ctxt,
4996 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4997 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL,
4998 (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004999 NULL, "(qualified | unqualified)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005000 attrValue, NULL, NULL, NULL);
5001 }
5002 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
William M. Bracke7091952004-05-11 15:09:58 +00005003 ns = schema->targetNamespace;
William M. Bracke7091952004-05-11 15:09:58 +00005004 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005005 }
5006 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005007 if (ret == NULL) {
5008 if (repName != NULL)
5009 xmlFree(repName);
5010 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005012 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5013 ret->node = node;
5014 /*
5015 * Check for illegal attributes.
5016 */
William M. Bracke7091952004-05-11 15:09:58 +00005017 attr = node->properties;
5018 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 if (attr->ns == NULL) {
5020 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5021 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5022 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5023 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5024 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5025 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
5026 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
5027 if (topLevel == 0) {
5028 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5029 /*
5030 * 3.3.6 : 3 If there is a non-·absent· {substitution
5031 * group affiliation}, then {scope} must be global.
5032 * TODO: This one is redundant, since the S4S does
5033 * prohibit this attribute on local declarations already;
5034 * so why an explicit error code? Weird spec.
William M. Brack2f2a6632004-08-20 23:09:47 +00005035 * TODO: Move this to the proper constraint layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005036 */
5037 xmlSchemaPIllegalAttrErr(ctxt,
5038 XML_SCHEMAP_E_PROPS_CORRECT_3,
5039 &repName, (xmlSchemaTypePtr) ret, attr);
5040 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5041 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5042 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005043
Daniel Veillardc0826a72004-08-10 14:17:33 +00005044 xmlSchemaPIllegalAttrErr(ctxt,
5045 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5046 &repName, (xmlSchemaTypePtr) ret, attr);
5047 }
5048 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5049 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5050 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5051
5052 xmlSchemaPIllegalAttrErr(ctxt,
5053 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5054 &repName, (xmlSchemaTypePtr) ret, attr);
5055 }
5056 }
5057 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5058
5059 xmlSchemaPIllegalAttrErr(ctxt,
5060 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5061 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005062 }
5063 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005064 }
William M. Bracke7091952004-05-11 15:09:58 +00005065 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 * Extract/validate attributes.
5067 */
5068 if (topLevel) {
5069 /*
5070 * Process top attributes of global element declarations here.
5071 */
5072 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5073 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5074 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5075 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5076 &(ret->substGroupNs), NULL, &(ret->substGroup));
5077 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5078 node, "abstract", 0))
5079 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5080 /*
5081 * Attribute "final".
5082 */
5083 attr = xmlSchemaGetPropNode(node, "final");
5084 if (attr == NULL) {
5085 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5086 } else {
5087 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5088 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5089 -1,
5090 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5091 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5092 xmlSchemaPSimpleTypeErr(ctxt,
5093 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5094 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005095 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005096 attrValue, NULL, NULL, NULL);
5097 }
5098 }
5099 }
5100 /*
5101 * Attribute "block".
5102 */
5103 attr = xmlSchemaGetPropNode(node, "block");
5104 if (attr == NULL) {
5105 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5106 } else {
5107 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5108 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5109 -1,
5110 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5111 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5112 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5113 xmlSchemaPSimpleTypeErr(ctxt,
5114 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5115 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005116 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005117 "restriction | substitution))", attrValue,
5118 NULL, NULL, NULL);
5119 }
5120 }
5121 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5122 node, "nillable", 0))
5123 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005124
Daniel Veillardc0826a72004-08-10 14:17:33 +00005125 xmlSchemaPValAttrQName(ctxt, schema,
5126 &repName, (xmlSchemaTypePtr) ret, node,
5127 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005128
Daniel Veillardc0826a72004-08-10 14:17:33 +00005129 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5130 attr = xmlSchemaGetPropNode(node, "fixed");
5131 if (attr != NULL) {
5132 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5133 if (ret->value != NULL) {
5134 /*
5135 * 3.3.3 : 1
5136 * default and fixed must not both be present.
5137 */
5138 xmlSchemaPMutualExclAttrErr(ctxt,
5139 XML_SCHEMAP_SRC_ELEMENT_1,
5140 &repName, (xmlSchemaTypePtr) ret, attr,
5141 "default", "fixed");
5142 } else {
5143 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5144 ret->value = fixed;
5145 }
5146 }
5147 }
5148 /*
5149 * Extract/validate common attributes.
5150 */
5151 /* TODO: Check ID: */
5152 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5153 ret->minOccurs = minOccurs;
5154 ret->maxOccurs = maxOccurs;
5155 if ((topLevel != 1) && (ret->maxOccurs != UNBOUNDED)) {
5156 /*
5157 * TODO: Maby we should better not create the element/particle,
5158 * if min/max is invalid, since it could confuse the build of the
5159 * content model.
5160 */
5161 /*
5162 * 3.9.6 Schema Component Constraint: Particle Correct
5163 *
5164 */
5165 if (maxOccurs < 1) {
5166 /*
5167 * 2.2 {max occurs} must be greater than or equal to 1.
5168 */
5169 xmlSchemaPCustomAttrErr(ctxt,
5170 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5171 &repName, (xmlSchemaTypePtr) ret,
5172 xmlSchemaGetPropNode(node, "maxOccurs"),
5173 "The value must be greater than or equal to 1");
5174 } else if (minOccurs > maxOccurs) {
5175 /*
5176 * 2.1 {min occurs} must not be greater than {max occurs}.
5177 */
5178 xmlSchemaPCustomAttrErr(ctxt,
5179 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5180 &repName, (xmlSchemaTypePtr) ret,
5181 xmlSchemaGetPropNode(node, "minOccurs"),
5182 "The value must not be greater than the value of 'maxOccurs'");
5183 }
5184 }
5185
5186 /*
5187 * And now for the children...
5188 */
5189 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005190 child = node->children;
5191 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005192 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5193 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005195 if (isRef) {
5196 if (child != NULL) {
5197 xmlSchemaPContentErr(ctxt,
5198 XML_SCHEMAP_SRC_ELEMENT_2_2,
5199 &repName, (xmlSchemaTypePtr) ret, node, child,
5200 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005201 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005202 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005203 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005204 /*
5205 * 3.3.3 : 3
5206 * "type" and either <simpleType> or <complexType> are mutually
5207 * exclusive
5208 */
William M. Bracke7091952004-05-11 15:09:58 +00005209 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005210 xmlSchemaPContentErr(ctxt,
5211 XML_SCHEMAP_SRC_ELEMENT_3,
5212 &repName, (xmlSchemaTypePtr) ret, node, child,
5213 "The attribute 'type' and the <complexType> child are "
5214 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005215 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005216 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005217 child = child->next;
5218 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005219 /*
5220 * 3.3.3 : 3
5221 * "type" and either <simpleType> or <complexType> are
5222 * mutually exclusive
5223 */
William M. Bracke7091952004-05-11 15:09:58 +00005224 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005225 xmlSchemaPContentErr(ctxt,
5226 XML_SCHEMAP_SRC_ELEMENT_3,
5227 &repName, (xmlSchemaTypePtr) ret, node, child,
5228 "The attribute 'type' and the <simpleType> child are "
5229 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005230 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005231 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005232 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005233 }
William M. Bracke7091952004-05-11 15:09:58 +00005234 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005235 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005236 TODO child = child->next;
5237 }
5238 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005239 xmlSchemaPContentErr(ctxt,
5240 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5241 &repName, (xmlSchemaTypePtr) ret, node, child,
5242 NULL, "(annotation?, ((simpleType | complexType)?, "
5243 "(unique | key | keyref)*))");
5244 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005245
Daniel Veillardc0826a72004-08-10 14:17:33 +00005246 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005247 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005248 /*
5249 * Cleanup.
5250 */
5251 if (repName != NULL)
5252 xmlFree(repName);
5253 /*
5254 * NOTE: Element Declaration Representation OK 4. will be checked at a
5255 * different layer.
5256 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005257 return (ret);
5258}
5259
5260/**
5261 * xmlSchemaParseUnion:
5262 * @ctxt: a schema validation context
5263 * @schema: the schema being built
5264 * @node: a subtree containing XML Schema informations
5265 *
5266 * parse a XML schema Union definition
5267 * *WARNING* this interface is highly subject to change
5268 *
William M. Bracke7091952004-05-11 15:09:58 +00005269 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 * 1 in case of success.
5271 */
5272static xmlSchemaTypePtr
5273xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005274 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005275{
5276 xmlSchemaTypePtr type, subtype, last = NULL;
5277 xmlNodePtr child = NULL;
5278 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005279 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005280
5281 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5282 return (NULL);
5283
William M. Brack2f2a6632004-08-20 23:09:47 +00005284 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5285 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 if (type == NULL)
5287 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005288 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005289 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005290 /*
5291 * Check for illegal attributes.
5292 */
5293 attr = node->properties;
5294 while (attr != NULL) {
5295 if (attr->ns == NULL) {
5296 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5297 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5298 xmlSchemaPIllegalAttrErr(ctxt,
5299 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5300 NULL, type, attr);
5301 }
5302 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5303 xmlSchemaPIllegalAttrErr(ctxt,
5304 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5305 NULL, type, attr);
5306 }
5307 attr = attr->next;
5308 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005309 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005310 /*
5311 * Attribute "memberTypes". This is a list of QNames.
5312 * TODO: Validate the QNames.
5313 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005314 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005315 /*
5316 * And now for the children...
5317 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005318 child = node->children;
5319 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005320 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5321 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005322 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005323 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005324 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005325 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005326 if (subtype != NULL) {
5327 if (last == NULL) {
5328 type->subtypes = subtype;
5329 last = subtype;
5330 } else {
5331 last->next = subtype;
5332 last = subtype;
5333 }
5334 last->next = NULL;
5335 }
5336 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 }
5338 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005339 /* TODO: Think about the error code. */
5340 xmlSchemaPContentErr(ctxt,
5341 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5342 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005343 }
5344 return (type);
5345}
5346
5347/**
5348 * xmlSchemaParseList:
5349 * @ctxt: a schema validation context
5350 * @schema: the schema being built
5351 * @node: a subtree containing XML Schema informations
5352 *
5353 * parse a XML schema List definition
5354 * *WARNING* this interface is highly subject to change
5355 *
William M. Bracke7091952004-05-11 15:09:58 +00005356 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005357 * 1 in case of success.
5358 */
5359static xmlSchemaTypePtr
5360xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005361 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005362{
5363 xmlSchemaTypePtr type, subtype;
5364 xmlNodePtr child = NULL;
5365 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005366 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005367
5368 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5369 return (NULL);
5370
William M. Brack2f2a6632004-08-20 23:09:47 +00005371 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5372 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 if (type == NULL)
5374 return (NULL);
5375 type->node = node;
5376 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005377 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005378 /*
5379 * Check for illegal attributes.
5380 */
5381 attr = node->properties;
5382 while (attr != NULL) {
5383 if (attr->ns == NULL) {
5384 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5385 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5386 xmlSchemaPIllegalAttrErr(ctxt,
5387 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5388 NULL, type, attr);
5389 }
5390 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5391 xmlSchemaPIllegalAttrErr(ctxt,
5392 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5393 NULL, type, attr);
5394 }
5395 attr = attr->next;
5396 }
5397 /*
5398 * Attribute "itemType".
5399 */
5400 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5401 node, "itemType", &(type->baseNs), NULL, &(type->base));
5402 /*
5403 * And now for the children...
5404 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005405 child = node->children;
5406 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5408 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005409 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005410 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005411 if (IS_SCHEMA(child, "simpleType")) {
5412 if (type->base != NULL) {
5413 xmlSchemaPCustomErr(ctxt,
5414 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5415 NULL, type, node,
5416 "The attribute 'itemType' and the <simpleType> child "
5417 "are mutually exclusive", NULL);
5418 } else {
5419 subtype = (xmlSchemaTypePtr)
5420 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5421 type->subtypes = subtype;
5422 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005423 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005424 }
5425 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005426 /* TODO: Think about the error code. */
5427 xmlSchemaPContentErr(ctxt,
5428 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5429 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005430 }
5431 return (type);
5432}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005433
Daniel Veillard4255d502002-04-16 15:50:10 +00005434/**
5435 * xmlSchemaParseSimpleType:
5436 * @ctxt: a schema validation context
5437 * @schema: the schema being built
5438 * @node: a subtree containing XML Schema informations
5439 *
5440 * parse a XML schema Simple Type definition
5441 * *WARNING* this interface is highly subject to change
5442 *
William M. Bracke7091952004-05-11 15:09:58 +00005443 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005444 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005445 */
5446static xmlSchemaTypePtr
5447xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005448 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005449{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005450 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005451 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005452 const xmlChar *attrValue = NULL;
5453 xmlChar *repName = NULL;
5454 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005455
5456 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5457 return (NULL);
5458
Daniel Veillardc0826a72004-08-10 14:17:33 +00005459 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005460
Daniel Veillardc0826a72004-08-10 14:17:33 +00005461 if (topLevel) {
5462 if (attr == NULL) {
5463 xmlSchemaPMissingAttrErr(ctxt,
5464 XML_SCHEMAP_S4S_ATTR_MISSING,
5465 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5466 "name", NULL);
5467 return (NULL);
5468 } else if (xmlSchemaPValAttrNode(ctxt,
5469 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5470 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005471 return (NULL);
5472 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005473 }
5474
5475 if (topLevel == 0) {
5476 char buf[100];
5477
Daniel Veillard01fa6152004-06-29 17:04:39 +00005478 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005479 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005481 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005482 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005483 if (type == NULL)
5484 return (NULL);
5485 type->node = node;
5486 type->type = XML_SCHEMA_TYPE_SIMPLE;
5487 /*
5488 * Check for illegal attributes.
5489 */
5490 attr = node->properties;
5491 while (attr != NULL) {
5492 if (attr->ns == NULL) {
5493 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5494 xmlSchemaPIllegalAttrErr(ctxt,
5495 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5496 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005497 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5499 xmlSchemaPIllegalAttrErr(ctxt,
5500 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5501 &repName, type, attr);
5502 }
5503 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005504 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 } else {
5506 /*
5507 * Parse as global simple type definition.
5508 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005509 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005510 if (type == NULL)
5511 return (NULL);
5512 type->node = node;
5513 type->type = XML_SCHEMA_TYPE_SIMPLE;
5514 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5515 /*
5516 * Check for illegal attributes.
5517 */
5518 attr = node->properties;
5519 while (attr != NULL) {
5520 if (attr->ns == NULL) {
5521 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5522 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5523 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5524 xmlSchemaPIllegalAttrErr(ctxt,
5525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5526 &repName, type, attr);
5527 }
5528 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5529 xmlSchemaPIllegalAttrErr(ctxt,
5530 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5531 &repName, type, attr);
5532 }
5533 attr = attr->next;
5534 }
5535 /*
5536 * Attribute "final".
5537 */
5538 attr = xmlSchemaGetPropNode(node, "final");
5539 if (attr == NULL) {
5540 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5541 } else {
5542 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5543 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5544 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5545 XML_SCHEMAS_TYPE_FINAL_LIST,
5546 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5547
5548 xmlSchemaPSimpleTypeErr(ctxt,
5549 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5550 &repName, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005551 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 attrValue, NULL, NULL, NULL);
5553 }
5554 }
5555 }
5556 /* TODO: Check id. */
5557 type->id = xmlSchemaGetProp(ctxt, node, "id");
5558 /*
5559 * And now for the children...
5560 */
5561 ctxtType = ctxt->ctxtType;
5562 ctxt->ctxtType = type;
5563 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005564 child = node->children;
5565 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005566 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5567 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005568 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005570 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005571 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005572 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005573 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005574 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005575 subtype = (xmlSchemaTypePtr)
5576 xmlSchemaParseList(ctxt, schema, child);
5577 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005578 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005579 subtype = (xmlSchemaTypePtr)
5580 xmlSchemaParseUnion(ctxt, schema, child);
5581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005582 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 type->subtypes = subtype;
5584 if ((child != NULL) || (subtype == NULL)) {
5585 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5586 &repName, type, node, child, NULL,
5587 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005588 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005589 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 if (repName != NULL)
5591 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005592
Daniel Veillard4255d502002-04-16 15:50:10 +00005593 return (type);
5594}
5595
5596
5597/**
5598 * xmlSchemaParseGroup:
5599 * @ctxt: a schema validation context
5600 * @schema: the schema being built
5601 * @node: a subtree containing XML Schema informations
5602 *
5603 * parse a XML schema Group definition
5604 * *WARNING* this interface is highly subject to change
5605 *
William M. Bracke7091952004-05-11 15:09:58 +00005606 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005607 * 1 in case of success.
5608 */
5609static xmlSchemaTypePtr
5610xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005611 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005612{
5613 xmlSchemaTypePtr type, subtype;
5614 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005615 const xmlChar *name;
5616 const xmlChar *ref = NULL, *refNs = NULL;
5617 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00005618
5619 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5620 return (NULL);
5621
5622
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005623 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005625 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5626 if (ref == NULL) {
5627 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005628 XML_SCHEMAP_GROUP_NONAME_NOREF,
5629 "Group definition or particle: One of the attributes \"name\" "
5630 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005631 return (NULL);
5632 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005633 if (refNs == NULL)
5634 refNs = schema->targetNamespace;
5635 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5636 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005637 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005638 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005639 if (type == NULL)
5640 return (NULL);
5641 type->node = node;
5642 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005643 if (topLevel)
5644 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005645 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005646 type->ref = ref;
5647 type->refNs = refNs;
5648 type->minOccurs = xmlGetMinOccurs(ctxt, node);
5649 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
5650
5651 child = node->children;
5652 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005653 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 }
5656 subtype = NULL;
5657 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 subtype = (xmlSchemaTypePtr)
5659 xmlSchemaParseAll(ctxt, schema, child);
5660 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 subtype = xmlSchemaParseChoice(ctxt, schema, child);
5663 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005664 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005665 subtype = (xmlSchemaTypePtr)
5666 xmlSchemaParseSequence(ctxt, schema, child);
5667 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 }
5669 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005672 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005673 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005674 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005675 }
5676
5677 return (type);
5678}
5679
5680/**
5681 * xmlSchemaParseAll:
5682 * @ctxt: a schema validation context
5683 * @schema: the schema being built
5684 * @node: a subtree containing XML Schema informations
5685 *
5686 * parse a XML schema All definition
5687 * *WARNING* this interface is highly subject to change
5688 *
William M. Bracke7091952004-05-11 15:09:58 +00005689 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 * 1 in case of success.
5691 */
5692static xmlSchemaTypePtr
5693xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005694 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005695{
5696 xmlSchemaTypePtr type, subtype, last = NULL;
5697 xmlNodePtr child = NULL;
5698 xmlChar name[30];
5699
5700 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5701 return (NULL);
5702
5703
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005704 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005705 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005706 if (type == NULL)
5707 return (NULL);
5708 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00005709 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005710 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005711 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005712 if (type->minOccurs > 1)
5713 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 "<all>: The value of the attribute \"minOccurs\" is invalid. "
5715 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005716 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005717 if (type->maxOccurs > 1)
5718 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005719 "<all>: The value of the attribute \"maxOccurs\" is invalid. "
5720 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005721
5722 child = node->children;
5723 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005724 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005726 }
5727 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 subtype = (xmlSchemaTypePtr)
5729 xmlSchemaParseElement(ctxt, schema, child, 0);
5730 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00005731 if (subtype->minOccurs > 1)
5732 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005733 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005734 NULL, NULL);
5735 if (subtype->maxOccurs > 1)
5736 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005738 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005739 if (last == NULL) {
5740 type->subtypes = subtype;
5741 last = subtype;
5742 } else {
5743 last->next = subtype;
5744 last = subtype;
5745 }
5746 last->next = NULL;
5747 }
5748 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005749 }
5750 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005751 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005753 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005754 }
5755
5756 return (type);
5757}
5758
5759/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005760 * xmlSchemaCleanupDoc:
5761 * @ctxt: a schema validation context
5762 * @node: the root of the document.
5763 *
5764 * removes unwanted nodes in a schemas document tree
5765 */
5766static void
5767xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
5768{
5769 xmlNodePtr delete, cur;
5770
5771 if ((ctxt == NULL) || (root == NULL)) return;
5772
5773 /*
5774 * Remove all the blank text nodes
5775 */
5776 delete = NULL;
5777 cur = root;
5778 while (cur != NULL) {
5779 if (delete != NULL) {
5780 xmlUnlinkNode(delete);
5781 xmlFreeNode(delete);
5782 delete = NULL;
5783 }
5784 if (cur->type == XML_TEXT_NODE) {
5785 if (IS_BLANK_NODE(cur)) {
5786 if (xmlNodeGetSpacePreserve(cur) != 1) {
5787 delete = cur;
5788 }
5789 }
5790 } else if ((cur->type != XML_ELEMENT_NODE) &&
5791 (cur->type != XML_CDATA_SECTION_NODE)) {
5792 delete = cur;
5793 goto skip_children;
5794 }
5795
5796 /*
5797 * Skip to next node
5798 */
5799 if (cur->children != NULL) {
5800 if ((cur->children->type != XML_ENTITY_DECL) &&
5801 (cur->children->type != XML_ENTITY_REF_NODE) &&
5802 (cur->children->type != XML_ENTITY_NODE)) {
5803 cur = cur->children;
5804 continue;
5805 }
5806 }
5807 skip_children:
5808 if (cur->next != NULL) {
5809 cur = cur->next;
5810 continue;
5811 }
5812
5813 do {
5814 cur = cur->parent;
5815 if (cur == NULL)
5816 break;
5817 if (cur == root) {
5818 cur = NULL;
5819 break;
5820 }
5821 if (cur->next != NULL) {
5822 cur = cur->next;
5823 break;
5824 }
5825 } while (cur != NULL);
5826 }
5827 if (delete != NULL) {
5828 xmlUnlinkNode(delete);
5829 xmlFreeNode(delete);
5830 delete = NULL;
5831 }
5832}
5833
William M. Brack2f2a6632004-08-20 23:09:47 +00005834
5835/**
5836 * xmlSchemaImportSchema
5837 *
5838 * @ctxt: a schema validation context
5839 * @schemaLocation: an URI defining where to find the imported schema
5840 *
5841 * import a XML schema
5842 * *WARNING* this interface is highly subject to change
5843 *
5844 * Returns -1 in case of error and 1 in case of success.
5845 */
5846#if 0
5847static xmlSchemaImportPtr
5848xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
5849 const xmlChar *schemaLocation)
5850{
5851 xmlSchemaImportPtr import;
5852 xmlSchemaParserCtxtPtr newctxt;
5853
5854 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
5855 if (newctxt == NULL) {
5856 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
5857 NULL);
5858 return (NULL);
5859 }
5860 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
5861 /* Keep the same dictionnary for parsing, really */
5862 xmlDictReference(ctxt->dict);
5863 newctxt->dict = ctxt->dict;
5864 newctxt->includes = 0;
5865 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
5866
5867 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
5868 ctxt->userData);
5869
5870 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
5871 if (import == NULL) {
5872 xmlSchemaPErrMemory(NULL, "allocating imported schema",
5873 NULL);
5874 xmlSchemaFreeParserCtxt(newctxt);
5875 return (NULL);
5876 }
5877
5878 memset(import, 0, sizeof(xmlSchemaImport));
5879 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
5880 import->schema = xmlSchemaParse(newctxt);
5881
5882 if (import->schema == NULL) {
5883 /* FIXME use another error enum here ? */
5884 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
5885 "Failed to import schema from location \"%s\".\n",
5886 schemaLocation, NULL);
5887
5888 xmlSchemaFreeParserCtxt(newctxt);
5889 /* The schemaLocation is held by the dictionary.
5890 if (import->schemaLocation != NULL)
5891 xmlFree((xmlChar *)import->schemaLocation);
5892 */
5893 xmlFree(import);
5894 return NULL;
5895 }
5896
5897 xmlSchemaFreeParserCtxt(newctxt);
5898 return import;
5899}
5900#endif
5901
5902static void
5903xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
5904{
5905 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5906 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
5907
5908 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5909 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
5910
5911 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
5912 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
5913 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
5914 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
5915 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
5916 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
5917 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
5918 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
5919
5920 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
5921 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
5922 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
5923 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
5924 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
5925 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
5926}
5927
5928static void
5929xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
5930 xmlSchemaPtr schema,
5931 xmlNodePtr node)
5932{
5933 xmlAttrPtr attr;
5934 const xmlChar *val;
5935
5936 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
5937 if (attr != NULL) {
5938 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5939 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
5940 XML_SCHEMAS_QUALIF_ELEM) != 0) {
5941 xmlSchemaPSimpleTypeErr(ctxt,
5942 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
5943 NULL, NULL, (xmlNodePtr) attr, NULL,
5944 "(qualified | unqualified)", val, NULL, NULL, NULL);
5945 }
5946 }
5947
5948 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
5949 if (attr != NULL) {
5950 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5951 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
5952 XML_SCHEMAS_QUALIF_ATTR) != 0) {
5953 xmlSchemaPSimpleTypeErr(ctxt,
5954 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
5955 NULL, NULL, (xmlNodePtr) attr, NULL,
5956 "(qualified | unqualified)", val, NULL, NULL, NULL);
5957 }
5958 }
5959
5960 attr = xmlSchemaGetPropNode(node, "finalDefault");
5961 if (attr != NULL) {
5962 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5963 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
5964 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
5965 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
5966 -1,
5967 XML_SCHEMAS_FINAL_DEFAULT_LIST,
5968 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
5969 xmlSchemaPSimpleTypeErr(ctxt,
5970 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5971 NULL, NULL, (xmlNodePtr) attr, NULL,
5972 "(#all | List of (extension | restriction | list | union))",
5973 val, NULL, NULL, NULL);
5974 }
5975 }
5976
5977 attr = xmlSchemaGetPropNode(node, "blockDefault");
5978 if (attr != NULL) {
5979 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5980 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
5981 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
5982 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
5983 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
5984 xmlSchemaPSimpleTypeErr(ctxt,
5985 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5986 NULL, NULL, (xmlNodePtr) attr, NULL,
5987 "(#all | List of (extension | restriction | substitution))",
5988 val, NULL, NULL, NULL);
5989 }
5990 }
5991}
5992
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005993/**
5994 * xmlSchemaParseSchemaTopLevel:
5995 * @ctxt: a schema validation context
5996 * @schema: the schemas
5997 * @nodes: the list of top level nodes
5998 *
5999 * Returns the internal XML Schema structure built from the resource or
6000 * NULL in case of error
6001 */
6002static void
6003xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6004 xmlSchemaPtr schema, xmlNodePtr nodes)
6005{
6006 xmlNodePtr child;
6007 xmlSchemaAnnotPtr annot;
6008
6009 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6010 return;
6011
6012 child = nodes;
6013 while ((IS_SCHEMA(child, "include")) ||
6014 (IS_SCHEMA(child, "import")) ||
6015 (IS_SCHEMA(child, "redefine")) ||
6016 (IS_SCHEMA(child, "annotation"))) {
6017 if (IS_SCHEMA(child, "annotation")) {
6018 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6019 if (schema->annot == NULL)
6020 schema->annot = annot;
6021 else
6022 xmlSchemaFreeAnnot(annot);
6023 } else if (IS_SCHEMA(child, "import")) {
6024 xmlSchemaParseImport(ctxt, schema, child);
6025 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006026 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006027 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006028 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006029 } else if (IS_SCHEMA(child, "redefine")) {
6030 TODO
6031 }
6032 child = child->next;
6033 }
6034 while (child != NULL) {
6035 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006036 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006037 child = child->next;
6038 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006039 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006040 child = child->next;
6041 } else if (IS_SCHEMA(child, "element")) {
6042 xmlSchemaParseElement(ctxt, schema, child, 1);
6043 child = child->next;
6044 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006045 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006046 child = child->next;
6047 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006048 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006049 child = child->next;
6050 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006051 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006052 child = child->next;
6053 } else if (IS_SCHEMA(child, "notation")) {
6054 xmlSchemaParseNotation(ctxt, schema, child);
6055 child = child->next;
6056 } else {
6057 xmlSchemaPErr2(ctxt, NULL, child,
6058 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006059 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006060 child->name, NULL);
6061 child = child->next;
6062 }
6063 while (IS_SCHEMA(child, "annotation")) {
6064 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6065 if (schema->annot == NULL)
6066 schema->annot = annot;
6067 else
6068 xmlSchemaFreeAnnot(annot);
6069 child = child->next;
6070 }
6071 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006072 ctxt->parentItem = NULL;
6073 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006074}
6075
William M. Brack2f2a6632004-08-20 23:09:47 +00006076
6077/**
6078 * xmlSchemaParseImport:
6079 * @ctxt: a schema validation context
6080 * @schema: the schema being built
6081 * @node: a subtree containing XML Schema informations
6082 *
6083 * parse a XML schema Import definition
6084 * *WARNING* this interface is highly subject to change
6085 *
6086 * Returns 0 in case of success, a positive error code if
6087 * not valid and -1 in case of an internal error.
6088 */
6089static int
6090xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6091 xmlNodePtr node)
6092{
6093 xmlNodePtr child = NULL;
6094 xmlSchemaImportPtr import = NULL;
6095 const xmlChar *namespace = NULL, *ns;
6096 const xmlChar *schemaLocation = NULL;
6097 const xmlChar *targetNamespace, *oldTNS, *url;
6098 xmlAttrPtr attr;
6099 xmlDocPtr doc;
6100 xmlNodePtr root;
6101 xmlChar *base = NULL;
6102 xmlChar *URI = NULL;
6103 int flags;
6104 xmlParserCtxtPtr parserCtxt;
6105
6106
6107 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6108 return (-1);
6109
6110 /*
6111 * Check for illegal attributes.
6112 */
6113 attr = node->properties;
6114 while (attr != NULL) {
6115 if (attr->ns == NULL) {
6116 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6117 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6118 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6119 xmlSchemaPIllegalAttrErr(ctxt,
6120 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6121 NULL, NULL, attr);
6122 }
6123 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6124 xmlSchemaPIllegalAttrErr(ctxt,
6125 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6126 NULL, NULL, attr);
6127 }
6128 attr = attr->next;
6129 }
6130 /*
6131 * Extract and validate attributes.
6132 */
6133 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6134 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6135 &namespace) != 0) {
6136 xmlSchemaPSimpleTypeErr(ctxt,
6137 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6138 NULL, NULL, node,
6139 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6140 NULL, namespace, NULL, NULL, NULL);
6141 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6142 }
6143
6144 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6145 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6146 &schemaLocation) != 0) {
6147 xmlSchemaPSimpleTypeErr(ctxt,
6148 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6149 NULL, NULL, node,
6150 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6151 NULL, namespace, NULL, NULL, NULL);
6152 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6153 }
6154 /*
6155 * And now for the children...
6156 */
6157 child = node->children;
6158 if (IS_SCHEMA(child, "annotation")) {
6159 /*
6160 * the annotation here is simply discarded ...
6161 */
6162 child = child->next;
6163 }
6164 if (child != NULL) {
6165 xmlSchemaPContentErr(ctxt,
6166 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6167 NULL, NULL, node, child, NULL,
6168 "(annotation?)");
6169 }
6170 /*
6171 * Apply additional constraints.
6172 */
6173 if (namespace != NULL) {
6174 /*
6175 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6176 * must not match the ·actual value· of the enclosing <schema>'s
6177 * targetNamespace [attribute].
6178 */
6179 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6180 xmlSchemaPCustomErr(ctxt,
6181 XML_SCHEMAP_SRC_IMPORT_1_1,
6182 NULL, NULL, node,
6183 "The value of the attribute 'namespace' must not match "
6184 "the target namespace '%s' of the importing schema",
6185 schema->targetNamespace);
6186 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6187 }
6188 } else {
6189 /*
6190 * 1.2 If the namespace [attribute] is not present, then the enclosing
6191 * <schema> must have a targetNamespace [attribute].
6192 */
6193 if (schema->targetNamespace == NULL) {
6194 xmlSchemaPCustomErr(ctxt,
6195 XML_SCHEMAP_SRC_IMPORT_1_2,
6196 NULL, NULL, node,
6197 "The attribute 'namespace' must be existent if "
6198 "the importing schema has no target namespace",
6199 NULL);
6200 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6201 }
6202 }
6203
6204 /*
6205 * Given that the schemaLocation [attribute] is only a hint, it is open
6206 * to applications to ignore all but the first <import> for a given
6207 * namespace, regardless of the ·actual value· of schemaLocation, but
6208 * such a strategy risks missing useful information when new
6209 * schemaLocations are offered.
6210 *
6211 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6212 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6213 * valid or not.
6214 * We will follow XSV here.
6215 */
6216 if (schemaLocation == NULL) {
6217 /*
6218 * Schema Document Location Strategy:
6219 *
6220 * 3 Based on the namespace name, identify an existing schema document,
6221 * either as a resource which is an XML document or a <schema> element
6222 * information item, in some local schema repository;
6223 *
6224 * 5 Attempt to resolve the namespace name to locate such a resource.
6225 *
6226 * NOTE: Those stategies are not supported, so we will skip.
6227 */
6228 return (0);
6229 }
6230 if (namespace == NULL)
6231 ns = XML_SCHEMAS_NO_NAMESPACE;
6232 else
6233 ns = namespace;
6234
6235 import = xmlHashLookup(schema->schemasImports, ns);
6236 if (import != NULL) {
6237 /*
6238 * There was a valid resource for the specified namespace already
6239 * defined, so skip.
6240 */
6241 return (0);
6242 }
6243 /*
6244 * Schema Document Location Strategy:
6245 *
6246 * 2 Based on the location URI, identify an existing schema document,
6247 * either as a resource which is an XML document or a <schema> element
6248 * information item, in some local schema repository;
6249 *
6250 * 4 Attempt to resolve the location URI, to locate a resource on the
6251 * web which is or contains or references a <schema> element;
6252 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6253 *
6254 */
6255
6256 base = xmlNodeGetBase(node->doc, node);
6257 if (base == NULL) {
6258 URI = xmlBuildURI(schemaLocation, node->doc->URL);
6259 } else {
6260 URI = xmlBuildURI(schemaLocation, base);
6261 xmlFree(base);
6262 }
6263 if (URI != NULL) {
6264 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
6265 xmlFree(URI);
6266 }
6267
6268 parserCtxt = xmlNewParserCtxt();
6269 if (parserCtxt == NULL) {
6270 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6271 "allocating a parser context", NULL);
6272 return(-1);
6273 }
6274
6275 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
6276 NULL, SCHEMAS_PARSE_OPTIONS);
6277
6278 /*
6279 * 2.1 The referent is (a fragment of) a resource which is an
6280 * XML document (see clause 1.1), which in turn corresponds to
6281 * a <schema> element information item in a well-formed information
6282 * set, which in turn corresponds to a valid schema.
6283 * TODO: What to do with the "fragment" stuff?
6284 *
6285 * 2.2 The referent is a <schema> element information item in
6286 * a well-formed information set, which in turn corresponds
6287 * to a valid schema.
6288 * NOTE: 2.2 won't apply, since only XML documents will be processed
6289 * here.
6290 */
6291 if (doc == NULL) {
6292 /*
6293 * It is *not* an error for the application schema reference
6294 * strategy to fail.
6295 *
6296 * If the doc is NULL and the parser error is an IO error we
6297 * will assume that the resource could not be located or accessed.
6298 *
6299 * TODO: Try to find specific error codes to react only on
6300 * localisation failures.
6301 *
6302 * TODO, FIXME: Check the spec: is a namespace added to the imported
6303 * namespaces, even if the schemaLocation did not provide
6304 * a resource? I guess so, since omitting the "schemaLocation"
6305 * attribute, imports a namespace as well.
6306 */
6307 if ((parserCtxt->errNo >= XML_IO_UNKNOWN) &&
6308 (parserCtxt->errNo < XML_XINCLUDE_RECURSION)) {
6309 xmlFreeParserCtxt(parserCtxt);
6310 return(0);
6311 }
6312
6313 xmlSchemaPCustomErr(ctxt,
6314 XML_SCHEMAP_SRC_IMPORT_2_1,
6315 NULL, NULL, node,
6316 "Failed to parse the resource '%s' for import",
6317 schemaLocation);
6318 xmlFreeParserCtxt(parserCtxt);
6319 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6320 }
6321 xmlFreeParserCtxt(parserCtxt);
6322
6323 root = xmlDocGetRootElement(doc);
6324 if (root == NULL) {
6325 xmlSchemaPCustomErr(ctxt,
6326 XML_SCHEMAP_SRC_IMPORT_2_1,
6327 NULL, NULL, node,
6328 "The XML document '%s' to be imported has no document "
6329 "element", schemaLocation);
6330 xmlFreeDoc(doc);
6331 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6332 }
6333
6334 xmlSchemaCleanupDoc(ctxt, root);
6335
6336 if (!IS_SCHEMA(root, "schema")) {
6337 xmlSchemaPCustomErr(ctxt,
6338 XML_SCHEMAP_SRC_IMPORT_2_1,
6339 NULL, NULL, node,
6340 "The XML document '%s' to be imported is not a XML schema document",
6341 schemaLocation);
6342 xmlFreeDoc(doc);
6343 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6344 }
6345 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6346 /*
6347 * Schema Representation Constraint: Import Constraints and Semantics
6348 */
6349 if (namespace == NULL) {
6350 if (targetNamespace != NULL) {
6351 xmlSchemaPCustomErr(ctxt,
6352 XML_SCHEMAP_SRC_IMPORT_3_2,
6353 NULL, NULL, node,
6354 "No 'namespace' attribute was "
6355 "specified, thus the XML schema to be imported "
6356 "must have no target namespace", NULL);
6357 xmlFreeDoc(doc);
6358 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6359 }
6360 } else {
6361 if (targetNamespace == NULL) {
6362 xmlSchemaPCustomErr(ctxt,
6363 XML_SCHEMAP_SRC_IMPORT_3_1,
6364 NULL, NULL, node,
6365 "The attribute 'namespace' requires the XML schema to be "
6366 "imported to have a target namespace of '%s'", namespace);
6367 xmlFreeDoc(doc);
6368 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6369 } else if (!xmlStrEqual(targetNamespace, namespace)) {
6370 xmlSchemaPCustomErrExt(ctxt,
6371 XML_SCHEMAP_SRC_IMPORT_3_1,
6372 NULL, NULL, node,
6373 "The value '%s' of the attribute 'namespace' is not "
6374 "identical to the target namespace '%s' of the "
6375 "XML schema to be imported",
6376 namespace, targetNamespace, NULL);
6377 xmlFreeDoc(doc);
6378 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6379 }
6380 }
6381 /*
6382 * Finally, import the schema.
6383 */
6384 if (schema->schemasImports == NULL) {
6385 schema->schemasImports = xmlHashCreate(10);
6386 if (schema->schemasImports == NULL) {
6387 xmlSchemaPErr2(ctxt, node, child,
6388 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6389 "Internal error: failed to build import table.\n",
6390 NULL, NULL);
6391 return (-1);
6392 }
6393 }
6394 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6395 if (import == NULL) {
6396 xmlSchemaPErrMemory(NULL, "allocating imported schema", NULL);
6397 xmlFreeDoc(doc);
6398 return (-1);
6399 }
6400 memset(import, 0, sizeof(xmlSchemaImport));
6401 import->schemaLocation = schemaLocation;
6402 import->doc = doc;
6403 xmlHashAddEntry(schema->schemasImports, ns, import);
6404 /*
6405 * Save and reset the context & schema.
6406 */
6407 url = ctxt->URL;
6408 /* TODO: Check this. */
6409 ctxt->URL = schemaLocation;
6410 flags = schema->flags;
6411 oldTNS = schema->targetNamespace;
6412
6413 xmlSchemaClearSchemaDefaults(schema);
6414 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6415 schema->targetNamespace = targetNamespace;
6416 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6417
6418 /*
6419 * Restore the context & schema.
6420 */
6421 schema->flags = flags;
6422 schema->targetNamespace = oldTNS;
6423 ctxt->URL = url;
6424
6425 return (1);
6426}
6427
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006428/**
6429 * xmlSchemaParseInclude:
6430 * @ctxt: a schema validation context
6431 * @schema: the schema being built
6432 * @node: a subtree containing XML Schema informations
6433 *
6434 * parse a XML schema Include definition
6435 *
William M. Bracke7091952004-05-11 15:09:58 +00006436 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006437 * 1 in case of success.
6438 */
6439static int
6440xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6441 xmlNodePtr node)
6442{
6443 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006445 xmlDocPtr doc;
6446 xmlNodePtr root;
6447 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006449 xmlAttrPtr attr;
6450 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006451
6452
6453 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6454 return (-1);
6455
6456 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006457 * Check for illegal attributes.
6458 */
6459 attr = node->properties;
6460 while (attr != NULL) {
6461 if (attr->ns == NULL) {
6462 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6463 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6464 xmlSchemaPIllegalAttrErr(ctxt,
6465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6466 NULL, NULL, attr);
6467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6469 xmlSchemaPIllegalAttrErr(ctxt,
6470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6471 NULL, NULL, attr);
6472 }
6473 attr = attr->next;
6474 }
6475 /*
6476 * Extract and validate attributes.
6477 */
6478 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006479 * Preliminary step, extract the URI-Reference for the include and
6480 * make an URI from the base.
6481 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006482 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6483 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006484 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006485 xmlChar *uri = NULL;
6486
6487 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6488 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6489 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006490 base = xmlNodeGetBase(node->doc, node);
6491 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006492 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006493 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006494 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006495 xmlFree(base);
6496 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006497 if (uri != NULL) {
6498 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6499 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006500 }
6501 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006502 xmlSchemaPMissingAttrErr(ctxt,
6503 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6504 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006505 return (-1);
6506 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006507 /*
6508 * And now for the children...
6509 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006510 child = node->children;
6511 while (IS_SCHEMA(child, "annotation")) {
6512 /*
6513 * the annotations here are simply discarded ...
6514 */
6515 child = child->next;
6516 }
6517 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006518 xmlSchemaPContentErr(ctxt,
6519 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6520 NULL, NULL, node, child, NULL,
6521 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006522 }
6523
6524 /*
6525 * First step is to parse the input document into an DOM/Infoset
6526 */
6527 doc = xmlReadFile((const char *) schemaLocation, NULL,
6528 SCHEMAS_PARSE_OPTIONS);
6529 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006530 /*
6531 * TODO: It is not an error for the ·actual value· of the
6532 * schemaLocation [attribute] to fail to resolve it all, in which
6533 * case no corresponding inclusion is performed.
6534 * So do we need a warning report here?
6535 */
6536 xmlSchemaPCustomErr(ctxt,
6537 XML_SCHEMAP_FAILED_LOAD,
6538 NULL, NULL, node,
6539 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006540 return(-1);
6541 }
6542
6543 /*
6544 * Then extract the root of the schema
6545 */
6546 root = xmlDocGetRootElement(doc);
6547 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006548 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006550 NULL, NULL, node,
6551 "The included document '%s' has no document "
6552 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006553 xmlFreeDoc(doc);
6554 return (-1);
6555 }
6556
6557 /*
6558 * Remove all the blank text nodes
6559 */
6560 xmlSchemaCleanupDoc(ctxt, root);
6561
6562 /*
6563 * Check the schemas top level element
6564 */
6565 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006566 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006568 NULL, NULL, node,
6569 "The document '%s' to be included is not a schema document",
6570 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006571 xmlFreeDoc(doc);
6572 return (-1);
6573 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574
William M. Brack2f2a6632004-08-20 23:09:47 +00006575 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006576 /*
6577 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6578 * value· is identical to the ·actual value· of the targetNamespace
6579 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6580 */
6581 if (targetNamespace != NULL) {
6582 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006583 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006584 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006585 NULL, NULL, node,
6586 "The target namespace of the included schema "
6587 "'%s' has to be absent, since the including schema "
6588 "has no target namespace",
6589 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006590 xmlFreeDoc(doc);
6591 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006592 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6593 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006594 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006595 NULL, NULL, node,
6596 "The target namespace '%s' of the included schema '%s' "
6597 "differs from '%s' of the including schema",
6598 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006599 xmlFreeDoc(doc);
6600 return (-1);
6601 }
6602 } else if (schema->targetNamespace != NULL) {
6603 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
6604 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
6605 } else
6606 wasConvertingNs = 1;
6607 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006608 /*
6609 * register the include
6610 */
6611 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
6612 if (include == NULL) {
6613 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
6614 xmlFreeDoc(doc);
6615 return (-1);
6616 }
6617
6618 memset(include, 0, sizeof(xmlSchemaInclude));
6619 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6620 include->doc = doc;
6621 include->next = schema->includes;
6622 schema->includes = include;
6623
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006624 /*
6625 * parse the declarations in the included file like if they
6626 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006627 */
6628 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006629 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006630 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006631 /*
6632 * The default values ("blockDefault", "elementFormDefault", etc.)
6633 * are set to the values of the included schema and restored afterwards.
6634 */
6635 saveFlags = schema->flags;
6636 xmlSchemaClearSchemaDefaults(schema);
6637 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006638 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00006639 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006640 /*
6641 * Remove the converting flag.
6642 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006643 if ((wasConvertingNs == 0) &&
6644 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006645 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006646 return (1);
6647}
6648
6649/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006650 * xmlSchemaParseChoice:
6651 * @ctxt: a schema validation context
6652 * @schema: the schema being built
6653 * @node: a subtree containing XML Schema informations
6654 *
6655 * parse a XML schema Choice definition
6656 * *WARNING* this interface is highly subject to change
6657 *
William M. Bracke7091952004-05-11 15:09:58 +00006658 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006659 * 1 in case of success.
6660 */
6661static xmlSchemaTypePtr
6662xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006663 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006664{
6665 xmlSchemaTypePtr type, subtype, last = NULL;
6666 xmlNodePtr child = NULL;
6667 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006668 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006669
6670 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6671 return (NULL);
6672
6673
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006674 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006675 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006676 if (type == NULL)
6677 return (NULL);
6678 type->node = node;
6679 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006680 /*
6681 * Check for illegal attributes.
6682 */
6683 attr = node->properties;
6684 while (attr != NULL) {
6685 if (attr->ns == NULL) {
6686 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6687 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6688 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6689 xmlSchemaPIllegalAttrErr(ctxt,
6690 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6691 NULL, type, attr);
6692 }
6693 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6694 xmlSchemaPIllegalAttrErr(ctxt,
6695 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6696 NULL, type, attr);
6697 }
6698 attr = attr->next;
6699 }
6700 /*
6701 * Extract and validate attributes.
6702 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006703 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006704 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6705 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brack2f2a6632004-08-20 23:09:47 +00006706 /*
6707 * And now for the children...
6708 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006709 child = node->children;
6710 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006711 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6712 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 }
6714 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006715 (IS_SCHEMA(child, "group")) ||
6716 (IS_SCHEMA(child, "any")) ||
6717 (IS_SCHEMA(child, "choice")) ||
6718 (IS_SCHEMA(child, "sequence"))) {
6719 subtype = NULL;
6720 if (IS_SCHEMA(child, "element")) {
6721 subtype = (xmlSchemaTypePtr)
6722 xmlSchemaParseElement(ctxt, schema, child, 0);
6723 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006724 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006725 } else if (IS_SCHEMA(child, "any")) {
6726 subtype = xmlSchemaParseAny(ctxt, schema, child);
6727 } else if (IS_SCHEMA(child, "sequence")) {
6728 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6729 } else if (IS_SCHEMA(child, "choice")) {
6730 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6731 }
6732 if (subtype != NULL) {
6733 if (last == NULL) {
6734 type->subtypes = subtype;
6735 last = subtype;
6736 } else {
6737 last->next = subtype;
6738 last = subtype;
6739 }
6740 last->next = NULL;
6741 }
6742 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 }
6744 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006745 /* TODO: error code. */
6746 xmlSchemaPContentErr(ctxt,
6747 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
6748 NULL, type, node, child, NULL,
6749 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006750 }
6751
6752 return (type);
6753}
6754
6755/**
6756 * xmlSchemaParseSequence:
6757 * @ctxt: a schema validation context
6758 * @schema: the schema being built
6759 * @node: a subtree containing XML Schema informations
6760 *
6761 * parse a XML schema Sequence definition
6762 * *WARNING* this interface is highly subject to change
6763 *
William M. Bracke7091952004-05-11 15:09:58 +00006764 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006765 * 1 in case of success.
6766 */
6767static xmlSchemaTypePtr
6768xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006769 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006770{
6771 xmlSchemaTypePtr type, subtype, last = NULL;
6772 xmlNodePtr child = NULL;
6773 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006774 xmlAttrPtr attr;
6775 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006776
6777 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6778 return (NULL);
6779
William M. Brack2f2a6632004-08-20 23:09:47 +00006780 oldcontainer = ctxt->container;
6781 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
6782 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006783 if (type == NULL)
6784 return (NULL);
6785 type->node = node;
6786 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00006787 /*
6788 * Check for illegal attributes.
6789 */
6790 attr = node->properties;
6791 while (attr != NULL) {
6792 if (attr->ns == NULL) {
6793 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6794 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6795 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
6796 xmlSchemaPIllegalAttrErr(ctxt,
6797 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6798 NULL, type, attr);
6799 }
6800 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6801 xmlSchemaPIllegalAttrErr(ctxt,
6802 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6803 NULL, type, attr);
6804 }
6805 attr = attr->next;
6806 }
6807 /*
6808 * Extract and validate attributes.
6809 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006810 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006811 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6812 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brack2f2a6632004-08-20 23:09:47 +00006813 /*
6814 * And now for the children...
6815 */
6816 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006817 child = node->children;
6818 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006819 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6820 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006821 }
6822 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006823 (IS_SCHEMA(child, "group")) ||
6824 (IS_SCHEMA(child, "any")) ||
6825 (IS_SCHEMA(child, "choice")) ||
6826 (IS_SCHEMA(child, "sequence"))) {
6827 subtype = NULL;
6828 if (IS_SCHEMA(child, "element")) {
6829 subtype = (xmlSchemaTypePtr)
6830 xmlSchemaParseElement(ctxt, schema, child, 0);
6831 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006832 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006833 } else if (IS_SCHEMA(child, "any")) {
6834 subtype = xmlSchemaParseAny(ctxt, schema, child);
6835 } else if (IS_SCHEMA(child, "choice")) {
6836 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6837 } else if (IS_SCHEMA(child, "sequence")) {
6838 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6839 }
6840 if (subtype != NULL) {
6841 if (last == NULL) {
6842 type->subtypes = subtype;
6843 last = subtype;
6844 } else {
6845 last->next = subtype;
6846 last = subtype;
6847 }
6848 last->next = NULL;
6849 }
6850 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006851 }
6852 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006853 xmlSchemaPContentErr(ctxt,
6854 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
6855 NULL, type, node, child, NULL,
6856 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006857 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006858 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006859
6860 return (type);
6861}
6862
6863/**
6864 * xmlSchemaParseRestriction:
6865 * @ctxt: a schema validation context
6866 * @schema: the schema being built
6867 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00006868 *
6869 * parse a XML schema Restriction definition
6870 * *WARNING* this interface is highly subject to change
6871 *
6872 * Returns the type definition or NULL in case of error
6873 */
6874static xmlSchemaTypePtr
6875xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006876 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006877{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006878 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006879 xmlNodePtr child = NULL;
6880 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006881 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00006882 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006883
6884 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6885 return (NULL);
6886
6887 oldcontainer = ctxt->container;
6888
William M. Brack2f2a6632004-08-20 23:09:47 +00006889 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
6890 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 if (type == NULL)
6892 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006893 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006894 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006895 /*
6896 * Check for illegal attributes.
6897 */
6898 attr = node->properties;
6899 while (attr != NULL) {
6900 if (attr->ns == NULL) {
6901 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6902 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
6903 xmlSchemaPIllegalAttrErr(ctxt,
6904 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6905 NULL, type, attr);
6906 }
6907 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6908 xmlSchemaPIllegalAttrErr(ctxt,
6909 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6910 NULL, type, attr);
6911 }
6912 attr = attr->next;
6913 }
6914 /*
6915 * Extract and validate attributes.
6916 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006917 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006918 /*
6919 * Attribute "base".
6920 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006921 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00006922 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
6924 /* TODO: Think about the error code. */
6925 xmlSchemaPMissingAttrErr(ctxt,
6926 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
6927 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006928 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006929 /*
6930 * And now for the children...
6931 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006932 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006933 child = node->children;
6934 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006935 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6936 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006937 }
6938 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006939 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
6940 if (IS_SCHEMA(child, "all")) {
6941 subtype = (xmlSchemaTypePtr)
6942 xmlSchemaParseAll(ctxt, schema, child);
6943 child = child->next;
6944 type->subtypes = subtype;
6945 } else if (IS_SCHEMA(child, "choice")) {
6946 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6947 child = child->next;
6948 type->subtypes = subtype;
6949 } else if (IS_SCHEMA(child, "sequence")) {
6950 subtype = (xmlSchemaTypePtr)
6951 xmlSchemaParseSequence(ctxt, schema, child);
6952 child = child->next;
6953 type->subtypes = subtype;
6954 } else if (IS_SCHEMA(child, "group")) {
6955 subtype = (xmlSchemaTypePtr)
6956 xmlSchemaParseGroup(ctxt, schema, child, 0);
6957 child = child->next;
6958 type->subtypes = subtype;
6959 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006960 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
6961 if (IS_SCHEMA(child, "simpleType")) {
6962 if (type->base != NULL) {
6963 /*
6964 * src-restriction-base-or-simpleType
6965 * Either the base [attribute] or the simpleType [child] of the
6966 * <restriction> element must be present, but not both.
6967 */
6968 xmlSchemaPContentErr(ctxt,
6969 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
6970 NULL, NULL, type->node, child,
6971 "The attribute 'base' and the <simpleType> child are "
6972 "mutually exclusive", NULL);
6973 } else {
6974 subtype = (xmlSchemaTypePtr)
6975 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6976 type->baseType = subtype;
6977 }
6978 child = child->next;
6979 }
6980 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006981 if (IS_SCHEMA(child, "simpleType")) {
6982 subtype = (xmlSchemaTypePtr)
6983 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006984 type->subtypes = subtype;
6985 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006986 }
6987 }
6988 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
6989 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
6990 xmlSchemaFacetPtr facet, lastfacet = NULL;
6991
Daniel Veillard01fa6152004-06-29 17:04:39 +00006992 /*
6993 * Add the facets to the parent simpleType/complexType.
6994 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006995 /*
6996 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
6997 * Simple Type Definition Schema Representation Constraint:
6998 * *Single Facet Value*
6999 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007000 while ((IS_SCHEMA(child, "minInclusive")) ||
7001 (IS_SCHEMA(child, "minExclusive")) ||
7002 (IS_SCHEMA(child, "maxInclusive")) ||
7003 (IS_SCHEMA(child, "maxExclusive")) ||
7004 (IS_SCHEMA(child, "totalDigits")) ||
7005 (IS_SCHEMA(child, "fractionDigits")) ||
7006 (IS_SCHEMA(child, "pattern")) ||
7007 (IS_SCHEMA(child, "enumeration")) ||
7008 (IS_SCHEMA(child, "whiteSpace")) ||
7009 (IS_SCHEMA(child, "length")) ||
7010 (IS_SCHEMA(child, "maxLength")) ||
7011 (IS_SCHEMA(child, "minLength"))) {
7012 facet = xmlSchemaParseFacet(ctxt, schema, child);
7013 if (facet != NULL) {
7014 if (lastfacet == NULL)
7015 ctxt->ctxtType->facets = facet;
7016 else
7017 lastfacet->next = facet;
7018 lastfacet = facet;
7019 lastfacet->next = NULL;
7020 }
7021 child = child->next;
7022 }
7023 /*
7024 * Create links for derivation and validation.
7025 */
7026 if (lastfacet != NULL) {
7027 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7028
7029 facet = ctxt->ctxtType->facets;
7030 do {
7031 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7032 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007033 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007034 xmlFree(facetLink);
7035 return (NULL);
7036 }
7037 facetLink->facet = facet;
7038 facetLink->next = NULL;
7039 if (lastFacetLink == NULL)
7040 ctxt->ctxtType->facetSet = facetLink;
7041 else
7042 lastFacetLink->next = facetLink;
7043 lastFacetLink = facetLink;
7044 facet = facet->next;
7045 } while (facet != NULL);
7046 }
7047 }
7048 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
William M. Brack2f2a6632004-08-20 23:09:47 +00007049 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007050 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007051 /* TODO: Think about the error code. */
7052 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7053 xmlSchemaPContentErr(ctxt,
7054 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7055 NULL, type, node, child, NULL,
7056 "annotation?, (group | all | choice | sequence)?, "
7057 "((attribute | attributeGroup)*, anyAttribute?))");
7058 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7059 xmlSchemaPContentErr(ctxt,
7060 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7061 NULL, type, node, child, NULL,
7062 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7063 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7064 "length | minLength | maxLength | enumeration | whiteSpace | "
7065 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7066 } else {
7067 /* Simple type */
7068 xmlSchemaPContentErr(ctxt,
7069 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7070 NULL, type, node, child, NULL,
7071 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7072 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7073 "length | minLength | maxLength | enumeration | whiteSpace | "
7074 "pattern)*))");
7075 }
7076 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007077 ctxt->container = oldcontainer;
7078 return (type);
7079}
7080
7081/**
7082 * xmlSchemaParseExtension:
7083 * @ctxt: a schema validation context
7084 * @schema: the schema being built
7085 * @node: a subtree containing XML Schema informations
7086 *
7087 * parse a XML schema Extension definition
7088 * *WARNING* this interface is highly subject to change
7089 *
7090 * Returns the type definition or NULL in case of error
7091 */
7092static xmlSchemaTypePtr
7093xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007094 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007095{
7096 xmlSchemaTypePtr type, subtype;
7097 xmlNodePtr child = NULL;
7098 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007099 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007100
7101 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7102 return (NULL);
7103
7104 oldcontainer = ctxt->container;
7105
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007106 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007107 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007108 if (type == NULL)
7109 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007110 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007111 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007112 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007113 ctxt->container = name;
7114
7115 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7116 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007117 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007118 "<extension>: The attribute \"base\" is missing.\n",
7119 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007120 }
7121 child = node->children;
7122 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007123 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7124 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007125 }
7126 subtype = NULL;
7127
7128 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 subtype = xmlSchemaParseAll(ctxt, schema, child);
7130 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007131 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007132 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007134 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007135 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7136 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007137 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007138 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007139 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007140 }
7141 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007142 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007143 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7144 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007145 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007146 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7147 "<extension> has unexpected content.\n", type->name,
7148 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007149 }
7150 ctxt->container = oldcontainer;
7151 return (type);
7152}
7153
7154/**
7155 * xmlSchemaParseSimpleContent:
7156 * @ctxt: a schema validation context
7157 * @schema: the schema being built
7158 * @node: a subtree containing XML Schema informations
7159 *
7160 * parse a XML schema SimpleContent definition
7161 * *WARNING* this interface is highly subject to change
7162 *
7163 * Returns the type definition or NULL in case of error
7164 */
7165static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007166xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7167 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007168{
7169 xmlSchemaTypePtr type, subtype;
7170 xmlNodePtr child = NULL;
7171 xmlChar name[30];
7172
7173 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7174 return (NULL);
7175
William M. Bracke7091952004-05-11 15:09:58 +00007176 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007177 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007178 if (type == NULL)
7179 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007180 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007181 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007182 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007183
7184 child = node->children;
7185 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007186 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7187 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007188 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007189 ctxt->parentItem = type;
7190 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007191 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007192 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007193 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007195 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007196 subtype = (xmlSchemaTypePtr)
7197 xmlSchemaParseExtension(ctxt, schema, child);
7198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007199 }
7200 type->subtypes = subtype;
7201 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007202 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007203 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7204 "<simpleContent> has unexpected content.\n",
7205 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007206 }
7207 return (type);
7208}
7209
7210/**
7211 * xmlSchemaParseComplexContent:
7212 * @ctxt: a schema validation context
7213 * @schema: the schema being built
7214 * @node: a subtree containing XML Schema informations
7215 *
7216 * parse a XML schema ComplexContent definition
7217 * *WARNING* this interface is highly subject to change
7218 *
7219 * Returns the type definition or NULL in case of error
7220 */
7221static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007222xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7223 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007224{
7225 xmlSchemaTypePtr type, subtype;
7226 xmlNodePtr child = NULL;
7227 xmlChar name[30];
7228
7229 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7230 return (NULL);
7231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007232 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007233 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007234 if (type == NULL)
7235 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007236 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007237 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007238 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007239
7240 child = node->children;
7241 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007242 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7243 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007244 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007245 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007246 subtype = NULL;
7247 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007248 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007249 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007250 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007251 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007252 subtype = (xmlSchemaTypePtr)
7253 xmlSchemaParseExtension(ctxt, schema, child);
7254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007255 }
7256 type->subtypes = subtype;
7257 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007258 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007259 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
7260 "<complexContent> has unexpected content.\n",
7261 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007262 }
7263 return (type);
7264}
7265
7266/**
7267 * xmlSchemaParseComplexType:
7268 * @ctxt: a schema validation context
7269 * @schema: the schema being built
7270 * @node: a subtree containing XML Schema informations
7271 *
7272 * parse a XML schema Complex Type definition
7273 * *WARNING* this interface is highly subject to change
7274 *
7275 * Returns the type definition or NULL in case of error
7276 */
7277static xmlSchemaTypePtr
7278xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007279 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007280{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007281 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007282 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007283 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00007284 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007285 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00007286
7287 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7288 return (NULL);
7289
Daniel Veillard01fa6152004-06-29 17:04:39 +00007290 ctxtType = ctxt->ctxtType;
7291
Daniel Veillard4255d502002-04-16 15:50:10 +00007292 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007293 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007295 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007296 name = (const xmlChar *)buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00007297 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007298 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007299
William M. Bracke7091952004-05-11 15:09:58 +00007300 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
William M. Brack2f2a6632004-08-20 23:09:47 +00007301 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007302 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007303 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00007304 return (NULL);
7305 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007306 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00007307 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00007308
Daniel Veillard4255d502002-04-16 15:50:10 +00007309 type->node = node;
7310 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00007311 if (topLevel)
7312 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007313 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007314 ctxt->container = name;
7315
7316 child = node->children;
7317 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007318 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7319 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007320 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007321 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007322 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00007323 /* 3.4.3 : 2.2
7324 * Specifying mixed='true' when the <simpleContent>
7325 * alternative is chosen has no effect
7326 */
7327 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7328 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007329 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7330 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007331 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007332 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7333 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007334 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007335 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007336
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007337 if (IS_SCHEMA(child, "all")) {
7338 subtype = xmlSchemaParseAll(ctxt, schema, child);
7339 child = child->next;
7340 } else if (IS_SCHEMA(child, "choice")) {
7341 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7342 child = child->next;
7343 } else if (IS_SCHEMA(child, "sequence")) {
7344 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7345 child = child->next;
7346 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007347 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007348 child = child->next;
7349 }
7350 if (subtype != NULL)
7351 type->subtypes = subtype;
7352 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00007353 }
7354 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007355 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007356 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
7357 "Complex type definition \"%s\" has unexpected content.\n",
7358 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007359 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007360 if (type->attributeWildcard != NULL)
7361 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00007362 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007363 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 return (type);
7365}
7366
Daniel Veillard4255d502002-04-16 15:50:10 +00007367/**
7368 * xmlSchemaParseSchema:
7369 * @ctxt: a schema validation context
7370 * @node: a subtree containing XML Schema informations
7371 *
7372 * parse a XML schema definition from a node set
7373 * *WARNING* this interface is highly subject to change
7374 *
7375 * Returns the internal XML Schema structure built from the resource or
7376 * NULL in case of error
7377 */
7378static xmlSchemaPtr
7379xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7380{
7381 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007382 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007383 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007385
7386 if ((ctxt == NULL) || (node == NULL))
7387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007388
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007389 nberrors = ctxt->nberrors;
7390 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007391 if (IS_SCHEMA(node, "schema")) {
7392 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007393 if (schema == NULL)
7394 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007395 attr = xmlSchemaGetPropNode(node, "targetNamespace");
7396 if (attr != NULL) {
7397 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7398 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
7399 /*
7400 * TODO: Should we proceed with an invalid target namespace?
7401 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007402 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
7403 } else {
7404 schema->targetNamespace = NULL;
7405 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007406 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007407 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007408 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7409 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7410
William M. Brack2f2a6632004-08-20 23:09:47 +00007411 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007412 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
7413 } else {
7414 xmlDocPtr doc;
7415
7416 doc = node->doc;
7417
7418 if ((doc != NULL) && (doc->URL != NULL)) {
7419 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7420 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007421 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007422 } else {
7423 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7424 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007425 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007426 }
7427 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007428 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007429 if (ctxt->nberrors != 0) {
7430 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007431 xmlSchemaFree(schema);
7432 schema = NULL;
7433 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007434 }
7435 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00007436#ifdef DEBUG
7437 if (schema == NULL)
7438 xmlGenericError(xmlGenericErrorContext,
7439 "xmlSchemaParse() failed\n");
7440#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007441 return (schema);
7442}
7443
7444/************************************************************************
7445 * *
7446 * Validating using Schemas *
7447 * *
7448 ************************************************************************/
7449
7450/************************************************************************
7451 * *
7452 * Reading/Writing Schemas *
7453 * *
7454 ************************************************************************/
7455
7456/**
7457 * xmlSchemaNewParserCtxt:
7458 * @URL: the location of the schema
7459 *
7460 * Create an XML Schemas parse context for that file/resource expected
7461 * to contain an XML Schemas file.
7462 *
7463 * Returns the parser context or NULL in case of error
7464 */
7465xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007466xmlSchemaNewParserCtxt(const char *URL)
7467{
Daniel Veillard4255d502002-04-16 15:50:10 +00007468 xmlSchemaParserCtxtPtr ret;
7469
7470 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007471 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007472
7473 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7474 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007475 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007476 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007477 return (NULL);
7478 }
7479 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007480 ret->dict = xmlDictCreate();
7481 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007482 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007483 return (ret);
7484}
7485
7486/**
Daniel Veillard6045c902002-10-09 21:13:59 +00007487 * xmlSchemaNewMemParserCtxt:
7488 * @buffer: a pointer to a char array containing the schemas
7489 * @size: the size of the array
7490 *
7491 * Create an XML Schemas parse context for that memory buffer expected
7492 * to contain an XML Schemas file.
7493 *
7494 * Returns the parser context or NULL in case of error
7495 */
7496xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007497xmlSchemaNewMemParserCtxt(const char *buffer, int size)
7498{
Daniel Veillard6045c902002-10-09 21:13:59 +00007499 xmlSchemaParserCtxtPtr ret;
7500
7501 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007502 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007503
7504 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7505 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007506 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007507 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00007508 return (NULL);
7509 }
7510 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7511 ret->buffer = buffer;
7512 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007513 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00007514 return (ret);
7515}
7516
7517/**
Daniel Veillard9d751502003-10-29 13:21:47 +00007518 * xmlSchemaNewDocParserCtxt:
7519 * @doc: a preparsed document tree
7520 *
7521 * Create an XML Schemas parse context for that document.
7522 * NB. The document may be modified during the parsing process.
7523 *
7524 * Returns the parser context or NULL in case of error
7525 */
7526xmlSchemaParserCtxtPtr
7527xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
7528{
7529 xmlSchemaParserCtxtPtr ret;
7530
7531 if (doc == NULL)
7532 return (NULL);
7533
7534 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7535 if (ret == NULL) {
7536 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
7537 NULL);
7538 return (NULL);
7539 }
7540 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
7541 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00007542 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00007543 /* The application has responsibility for the document */
7544 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00007545
7546 return (ret);
7547}
7548
7549/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007550 * xmlSchemaFreeParserCtxt:
7551 * @ctxt: the schema parser context
7552 *
7553 * Free the resources associated to the schema parser context
7554 */
7555void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
7557{
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007559 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00007560 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007561 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007562 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00007563 xmlFree(ctxt);
7564}
7565
7566/************************************************************************
7567 * *
7568 * Building the content models *
7569 * *
7570 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007571
Daniel Veillard4255d502002-04-16 15:50:10 +00007572/**
7573 * xmlSchemaBuildAContentModel:
7574 * @type: the schema type definition
7575 * @ctxt: the schema parser context
7576 * @name: the element name whose content is being built
7577 *
7578 * Generate the automata sequence needed for that type
7579 */
7580static void
7581xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007582 xmlSchemaParserCtxtPtr ctxt,
7583 const xmlChar * name)
7584{
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007586 xmlGenericError(xmlGenericErrorContext,
7587 "Found unexpected type = NULL in %s content model\n",
7588 name);
7589 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007590 }
7591 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007592 case XML_SCHEMA_TYPE_ANY: {
7593 xmlAutomataStatePtr start, end;
7594 xmlSchemaWildcardPtr wild;
7595 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00007596
Daniel Veillardc0826a72004-08-10 14:17:33 +00007597 wild = type->attributeWildcard;
7598
7599 if (wild == NULL) {
7600 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
7601 "Internal error: xmlSchemaBuildAContentModel, "
7602 "no wildcard on xsd:any.\n", NULL, NULL);
7603 return;
7604 }
7605
7606 start = ctxt->state;
7607 end = xmlAutomataNewState(ctxt->am);
7608
7609 if (type->maxOccurs == 1) {
7610 if (wild->any == 1) {
7611 /*
7612 * We need to add both transitions:
7613 *
7614 * 1. the {"*", "*"} for elements in a namespace.
7615 */
7616 ctxt->state =
7617 xmlAutomataNewTransition2(ctxt->am,
7618 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7619 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7620 /*
7621 * 2. the {"*"} for elements in no namespace.
7622 */
7623 ctxt->state =
7624 xmlAutomataNewTransition2(ctxt->am,
7625 start, NULL, BAD_CAST "*", NULL, type);
7626 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7627
7628 } else if (wild->nsSet != NULL) {
7629 ns = wild->nsSet;
7630 do {
7631 ctxt->state = start;
7632 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7633 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
7634 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7635 ns = ns->next;
7636 } while (ns != NULL);
7637
7638 } else if (wild->negNsSet != NULL) {
7639 xmlAutomataStatePtr deadEnd;
7640
7641 deadEnd = xmlAutomataNewState(ctxt->am);
7642 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7643 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7644 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7645 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7646 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7647 }
7648 } else {
7649 int counter;
7650 xmlAutomataStatePtr hop;
7651 int maxOccurs =
7652 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
7653 int minOccurs =
7654 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
7655
7656 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
7657 hop = xmlAutomataNewState(ctxt->am);
7658 if (wild->any == 1) {
7659 ctxt->state =
7660 xmlAutomataNewTransition2(ctxt->am,
7661 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7662 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7663 ctxt->state =
7664 xmlAutomataNewTransition2(ctxt->am,
7665 start, NULL, BAD_CAST "*", NULL, type);
7666 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7667 } else if (wild->nsSet != NULL) {
7668 ns = wild->nsSet;
7669 do {
7670 ctxt->state =
7671 xmlAutomataNewTransition2(ctxt->am,
7672 start, NULL, BAD_CAST "*", ns->value, type);
7673 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7674 ns = ns->next;
7675 } while (ns != NULL);
7676
7677 } else if (wild->negNsSet != NULL) {
7678 xmlAutomataStatePtr deadEnd;
7679
7680 deadEnd = xmlAutomataNewState(ctxt->am);
7681 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7682 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7683 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7684 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7685 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7686 }
7687 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
7688 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
7689 }
7690 if (type->minOccurs == 0) {
7691 xmlAutomataNewEpsilon(ctxt->am, start, end);
7692 }
7693 ctxt->state = end;
7694 break;
7695 }
7696 case XML_SCHEMA_TYPE_ELEMENT:{
7697 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
7698
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007699 /* TODO : handle the namespace too */
7700 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007701
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007702 if (elem->maxOccurs >= UNBOUNDED) {
7703 if (elem->minOccurs > 1) {
7704 xmlAutomataStatePtr tmp;
7705 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007707 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7708 oldstate,
7709 NULL);
7710 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007711
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007712 counter = xmlAutomataNewCounter(ctxt->am,
7713 elem->minOccurs -
7714 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00007715
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007716 if (elem->refDecl != NULL) {
7717 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7718 elem->refDecl,
7719 ctxt,
7720 elem->refDecl->
7721 name);
7722 } else {
7723 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007724 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007725 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007726 elem->name,
7727 elem->targetNamespace,
7728 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007729 }
7730 tmp = ctxt->state;
7731 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7732 counter);
7733 ctxt->state =
7734 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7735 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00007736
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007737 } else {
7738 if (elem->refDecl != NULL) {
7739 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7740 elem->refDecl,
7741 ctxt,
7742 elem->refDecl->
7743 name);
7744 } else {
7745 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007746 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007747 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007748 elem->name,
7749 elem->targetNamespace,
7750 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007751 }
7752 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7753 oldstate);
7754 if (elem->minOccurs == 0) {
7755 /* basically an elem* */
7756 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7757 ctxt->state);
7758 }
7759 }
7760 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
7761 xmlAutomataStatePtr tmp;
7762 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007763
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007764 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7765 oldstate, NULL);
7766 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007767
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007768 counter = xmlAutomataNewCounter(ctxt->am,
7769 elem->minOccurs - 1,
7770 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007771
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007772 if (elem->refDecl != NULL) {
7773 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7774 elem->refDecl, ctxt,
7775 elem->refDecl->name);
7776 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007777 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007778 ctxt->state,
7779 NULL,
7780 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007781 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007782 type);
7783 }
7784 tmp = ctxt->state;
7785 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7786 counter);
7787 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
7788 NULL,
7789 counter);
7790 if (elem->minOccurs == 0) {
7791 /* basically an elem? */
7792 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7793 ctxt->state);
7794 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00007795
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 } else {
7797 if (elem->refDecl != NULL) {
7798 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7799 elem->refDecl, ctxt,
7800 elem->refDecl->name);
7801 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007802 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007803 ctxt->state,
7804 NULL,
7805 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007806 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007807 type);
7808 }
7809 if (elem->minOccurs == 0) {
7810 /* basically an elem? */
7811 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7812 ctxt->state);
7813 }
7814 }
7815 break;
7816 }
7817 case XML_SCHEMA_TYPE_SEQUENCE:{
7818 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007819
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007820 /*
7821 * If max and min occurances are default (1) then
7822 * simply iterate over the subtypes
7823 */
7824 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
7825 subtypes = type->subtypes;
7826 while (subtypes != NULL) {
7827 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7828 subtypes = subtypes->next;
7829 }
7830 } else {
7831 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007832
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007833 if (type->maxOccurs >= UNBOUNDED) {
7834 if (type->minOccurs > 1) {
7835 xmlAutomataStatePtr tmp;
7836 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007837
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007838 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7839 oldstate,
7840 NULL);
7841 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007842
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007843 counter = xmlAutomataNewCounter(ctxt->am,
7844 type->
7845 minOccurs - 1,
7846 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007847
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007848 subtypes = type->subtypes;
7849 while (subtypes != NULL) {
7850 xmlSchemaBuildAContentModel(subtypes, ctxt,
7851 name);
7852 subtypes = subtypes->next;
7853 }
7854 tmp = ctxt->state;
7855 xmlAutomataNewCountedTrans(ctxt->am, tmp,
7856 oldstate, counter);
7857 ctxt->state =
7858 xmlAutomataNewCounterTrans(ctxt->am, tmp,
7859 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007860
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007861 } else {
7862 subtypes = type->subtypes;
7863 while (subtypes != NULL) {
7864 xmlSchemaBuildAContentModel(subtypes, ctxt,
7865 name);
7866 subtypes = subtypes->next;
7867 }
7868 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7869 oldstate);
7870 if (type->minOccurs == 0) {
7871 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7872 ctxt->state);
7873 }
7874 }
7875 } else if ((type->maxOccurs > 1)
7876 || (type->minOccurs > 1)) {
7877 xmlAutomataStatePtr tmp;
7878 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007879
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007880 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7881 oldstate,
7882 NULL);
7883 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00007884
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007885 counter = xmlAutomataNewCounter(ctxt->am,
7886 type->minOccurs -
7887 1,
7888 type->maxOccurs -
7889 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007890
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007891 subtypes = type->subtypes;
7892 while (subtypes != NULL) {
7893 xmlSchemaBuildAContentModel(subtypes, ctxt,
7894 name);
7895 subtypes = subtypes->next;
7896 }
7897 tmp = ctxt->state;
7898 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7899 counter);
7900 ctxt->state =
7901 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7902 counter);
7903 if (type->minOccurs == 0) {
7904 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7905 ctxt->state);
7906 }
Daniel Veillardb509f152002-04-17 16:28:10 +00007907
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007908 } else {
7909 subtypes = type->subtypes;
7910 while (subtypes != NULL) {
7911 xmlSchemaBuildAContentModel(subtypes, ctxt,
7912 name);
7913 subtypes = subtypes->next;
7914 }
7915 if (type->minOccurs == 0) {
7916 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7917 ctxt->state);
7918 }
7919 }
7920 }
7921 break;
7922 }
7923 case XML_SCHEMA_TYPE_CHOICE:{
7924 xmlSchemaTypePtr subtypes;
7925 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00007926
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007927 start = ctxt->state;
7928 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00007929
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007930 /*
7931 * iterate over the subtypes and remerge the end with an
7932 * epsilon transition
7933 */
7934 if (type->maxOccurs == 1) {
7935 subtypes = type->subtypes;
7936 while (subtypes != NULL) {
7937 ctxt->state = start;
7938 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7939 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7940 subtypes = subtypes->next;
7941 }
7942 } else {
7943 int counter;
7944 xmlAutomataStatePtr hop;
7945 int maxOccurs = type->maxOccurs == UNBOUNDED ?
7946 UNBOUNDED : type->maxOccurs - 1;
7947 int minOccurs =
7948 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00007949
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007950 /*
7951 * use a counter to keep track of the number of transtions
7952 * which went through the choice.
7953 */
7954 counter =
7955 xmlAutomataNewCounter(ctxt->am, minOccurs,
7956 maxOccurs);
7957 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00007958
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007959 subtypes = type->subtypes;
7960 while (subtypes != NULL) {
7961 ctxt->state = start;
7962 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7963 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7964 subtypes = subtypes->next;
7965 }
7966 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
7967 counter);
7968 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
7969 counter);
7970 }
7971 if (type->minOccurs == 0) {
7972 xmlAutomataNewEpsilon(ctxt->am, start, end);
7973 }
7974 ctxt->state = end;
7975 break;
7976 }
7977 case XML_SCHEMA_TYPE_ALL:{
7978 xmlAutomataStatePtr start;
7979 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007980
Daniel Veillard3646d642004-06-02 19:19:14 +00007981 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007982 int lax;
7983
7984 subtypes = type->subtypes;
7985 if (subtypes == NULL)
7986 break;
7987 start = ctxt->state;
7988 while (subtypes != NULL) {
7989 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00007990 /*
7991 * the following 'if' was needed to fix bug 139897
7992 * not quite sure why it only needs to be done for
7993 * elements with a 'ref', but it seems to work ok.
7994 */
7995 if (subtypes->ref != NULL)
7996 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00007997 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007998 /* TODO : handle the namespace too */
7999 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
8000 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
8001 ctxt->state, elem->name, 1,
8002 1, subtypes);
8003 } else {
8004 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
8005 ctxt->state, elem->name,
8006 elem->minOccurs,
8007 elem->maxOccurs,
8008 subtypes);
8009 }
8010 subtypes = subtypes->next;
8011 }
8012 lax = type->minOccurs == 0;
8013 ctxt->state =
8014 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8015 lax);
8016 break;
8017 }
8018 case XML_SCHEMA_TYPE_RESTRICTION:
8019 if (type->subtypes != NULL)
8020 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8021 break;
8022 case XML_SCHEMA_TYPE_EXTENSION:
8023 if (type->baseType != NULL) {
8024 xmlSchemaTypePtr subtypes;
8025
Daniel Veillardf7627552004-04-22 07:15:40 +00008026 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008027 /* TODO: Change the error code. */
8028 xmlSchemaPCustomErr(ctxt,
8029 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8030 NULL, type, type->node,
8031 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008032 return;
8033 }
8034 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008035 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008036 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008037 subtypes = type->subtypes;
8038 while (subtypes != NULL) {
8039 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8040 subtypes = subtypes->next;
8041 }
8042 } else if (type->subtypes != NULL)
8043 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8044 break;
8045 case XML_SCHEMA_TYPE_GROUP:
8046 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00008047 xmlSchemaTypePtr rgroup;
8048 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008049 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00008050 type->refNs);
8051 if (rgroup == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008052 xmlSchemaPResCompAttrErr(ctxt,
8053 XML_SCHEMAP_SRC_RESOLVE,
8054 NULL, type, NULL,
8055 "ref", type->ref, type->refNs,
8056 XML_SCHEMA_TYPE_GROUP, NULL);
William M. Brack29aa7722004-05-12 00:27:56 +00008057 return;
8058 }
8059 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
8060 break;
8061 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008062 }
8063 case XML_SCHEMA_TYPE_COMPLEX:
8064 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8065 if (type->subtypes != NULL)
8066 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8067 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008068 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8069 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008070 default:
8071 xmlGenericError(xmlGenericErrorContext,
8072 "Found unexpected type %d in %s content model\n",
8073 type->type, name);
8074 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008075 }
8076}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008077
Daniel Veillard4255d502002-04-16 15:50:10 +00008078/**
8079 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008080 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00008081 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008082 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008083 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008084 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00008085 */
8086static void
8087xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008088 xmlSchemaParserCtxtPtr ctxt,
8089 const xmlChar * name)
8090{
Daniel Veillard4255d502002-04-16 15:50:10 +00008091 xmlAutomataStatePtr start;
8092
Daniel Veillard4255d502002-04-16 15:50:10 +00008093 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008094 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008095 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008096 elem->contentType = XML_SCHEMA_CONTENT_ANY;
8097 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00008098 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008099 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008100 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008101 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8102 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008103 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008104
8105#ifdef DEBUG_CONTENT
8106 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008107 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008108#endif
8109
Daniel Veillard4255d502002-04-16 15:50:10 +00008110 ctxt->am = xmlNewAutomata();
8111 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008112 xmlGenericError(xmlGenericErrorContext,
8113 "Cannot create automata for elem %s\n", name);
8114 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008115 }
8116 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
8117 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
8118 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00008119 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008120 if (elem->contModel == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008121 xmlSchemaPCustomErr(ctxt, XML_SCHEMAS_ERR_INTERNAL,
8122 NULL, (xmlSchemaTypePtr) elem, NULL,
8123 "Failed to compile the content model", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008124 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008125 xmlSchemaPCustomErr(ctxt, XML_SCHEMAS_ERR_NOTDETERMINIST,
8126 NULL, (xmlSchemaTypePtr) elem, NULL,
8127 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008128 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008129#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008130 xmlGenericError(xmlGenericErrorContext,
8131 "Content model of %s:\n", name);
8132 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008133#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008134 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008135 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008136 xmlFreeAutomata(ctxt->am);
8137 ctxt->am = NULL;
8138}
8139
8140/**
8141 * xmlSchemaRefFixupCallback:
8142 * @elem: the schema element context
8143 * @ctxt: the schema parser context
8144 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145 * Resolves the references of an element declaration
8146 * or particle, which has an element declaration as it's
8147 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008148 */
8149static void
8150xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008151 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008152 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008153 const xmlChar * context ATTRIBUTE_UNUSED,
8154 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008155{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 if ((ctxt == NULL) || (elem == NULL) ||
8157 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008158 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008159 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008160 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008161 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008162
Daniel Veillardc0826a72004-08-10 14:17:33 +00008163 /*
8164 * TODO: Evaluate, what errors could occur if the declaration is not
8165 * found. It might be possible that the "typefixup" might crash if
8166 * no ref declaration was found.
8167 */
Daniel Veillardf2a12832003-11-24 13:04:35 +00008168 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008169 if (elemDecl == NULL) {
8170 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008171 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008172 NULL, (xmlSchemaTypePtr) elem, elem->node,
8173 "ref", elem->ref, elem->refNs,
8174 XML_SCHEMA_TYPE_ELEMENT, NULL);
8175 } else
8176 elem->refDecl = elemDecl;
8177 } else {
8178 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8179 xmlSchemaTypePtr type;
8180
8181 /* (type definition) ... otherwise the type definition ·resolved·
8182 * to by the ·actual value· of the type [attribute] ...
8183 */
8184 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8185 elem->namedTypeNs);
8186 if (type == NULL) {
8187 xmlSchemaPResCompAttrErr(ctxt,
8188 XML_SCHEMAP_SRC_RESOLVE,
8189 NULL, (xmlSchemaTypePtr) elem, elem->node,
8190 "type", elem->namedType, elem->namedTypeNs,
8191 XML_SCHEMA_TYPE_BASIC, "type definition");
8192 } else
8193 elem->subtypes = type;
8194 }
8195 if (elem->substGroup != NULL) {
8196 xmlSchemaElementPtr substHead;
8197
8198 /*
8199 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8200 * substitutionGroup?
8201 */
8202 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
8203 elem->substGroupNs, 0);
8204 if (substHead == NULL) {
8205 xmlSchemaPResCompAttrErr(ctxt,
8206 XML_SCHEMAP_SRC_RESOLVE,
8207 NULL, (xmlSchemaTypePtr) elem, NULL,
8208 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8209 XML_SCHEMA_TYPE_ELEMENT, NULL);
8210 } else {
8211 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8212 /*
8213 * (type definition)...otherwise the {type definition} of the
8214 * element declaration ·resolved· to by the ·actual value· of
8215 * the substitutionGroup [attribute], if present
8216 */
8217 if (elem->subtypes == NULL)
8218 elem->subtypes = substHead->subtypes;
8219 }
8220 }
8221 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8222 (elem->substGroup == NULL))
8223 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8224 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008225}
8226
William M. Bracke7091952004-05-11 15:09:58 +00008227/**
8228 * xmlSchemaParseListRefFixup:
8229 * @type: the schema type definition
8230 * @ctxt: the schema parser context
8231 *
8232 * Fixup of the itemType reference of the list type.
8233 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008234static void
William M. Bracke7091952004-05-11 15:09:58 +00008235xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008236{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008237
Daniel Veillard01fa6152004-06-29 17:04:39 +00008238 if (((type->base == NULL) &&
8239 (type->subtypes == NULL)) ||
8240 ((type->base != NULL) &&
8241 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008242 /*
8243 * src-list-itemType-or-simpleType
8244 * Either the itemType [attribute] or the <simpleType> [child] of
8245 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008247 /*
8248 * TODO: Move this to the parse function.
8249 */
8250 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008251 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008252 NULL, type, type->node,
8253 "The attribute 'itemType' and the <simpleType> child "
8254 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008255 } else if (type->base!= NULL) {
8256 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
8257 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008258 xmlSchemaPResCompAttrErr(ctxt,
8259 XML_SCHEMAP_SRC_RESOLVE,
8260 NULL, type, type->node,
8261 "itemType", type->base, type->baseNs,
8262 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008263 }
8264 }
8265 if ((type->subtypes != NULL) &&
8266 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8267 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008268}
8269
8270/**
8271 * xmlSchemaParseUnionRefCheck:
8272 * @typeDecl: the schema type definition
8273 * @ctxt: the schema parser context
8274 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00008275 * Checks and builds the memberTypes of the union type.
8276 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00008277 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008278static int
William M. Bracke7091952004-05-11 15:09:58 +00008279xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00008280 xmlSchemaParserCtxtPtr ctxt)
8281{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008282
Daniel Veillard01fa6152004-06-29 17:04:39 +00008283 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
8284 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00008285
Daniel Veillard01fa6152004-06-29 17:04:39 +00008286 /* 1 If the <union> alternative is chosen, then [Definition:]
8287 * define the explicit members as the type definitions ·resolved·
8288 * to by the items in the ·actual value· of the memberTypes [attribute],
8289 * if any, followed by the type definitions corresponding to the
8290 * <simpleType>s among the [children] of <union>, if any.
8291 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008292
Daniel Veillard01fa6152004-06-29 17:04:39 +00008293 if (type->type != XML_SCHEMA_TYPE_UNION)
8294 return (-1);
8295 if (ctxt->ctxtType == NULL) {
8296 xmlSchemaPErr(ctxt, type->node,
8297 XML_SCHEMAS_ERR_INTERNAL,
8298 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
8299 "available", NULL, NULL);
8300 return (-1);
8301 }
8302 /*
8303 * src-union-memberTypes-or-simpleTypes
8304 * Either the memberTypes [attribute] of the <union> element must
8305 * be non-empty or there must be at least one simpleType [child].
8306 */
8307 if ((type->base == NULL) &&
8308 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008309 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008310 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008311 NULL, NULL, type->node,
8312 "Either the attribute 'memberTypes' must be non-empty "
8313 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008314 }
8315
8316 ctxtType = ctxt->ctxtType;
8317 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008318 xmlAttrPtr attr;
8319 const xmlChar *cur, *end;
8320 xmlChar *tmp;
8321 const xmlChar *localName, *uri;
8322
8323 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00008324 cur = type->base;
8325 do {
8326 while (IS_BLANK_CH(*cur))
8327 cur++;
8328 end = cur;
8329 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8330 end++;
8331 if (end == cur)
8332 break;
8333 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008334 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
8335 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
8336 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008337 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008338 xmlSchemaPResCompAttrErr(ctxt,
8339 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
8340 NULL, NULL, type->node, "memberTypes", localName, uri,
8341 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008342 } else {
8343 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8344 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8345 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8346 if (link == NULL) {
8347 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8348 return (-1);
8349 }
8350 link->type = memberType;
8351 link->next = NULL;
8352 if (lastLink == NULL)
8353 ctxtType->memberTypes = link;
8354 else
8355 lastLink->next = link;
8356 lastLink = link;
8357 }
8358 xmlFree(tmp);
8359 cur = end;
8360 } while (*cur != 0);
8361 }
8362 /*
8363 * Add local simple types,
8364 */
8365 memberType = type->subtypes;
8366 while (memberType != NULL) {
8367 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8368 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8369 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8370 if (link == NULL) {
8371 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8372 return (-1);
8373 }
8374 link->type = memberType;
8375 link->next = NULL;
8376 if (lastLink == NULL)
8377 ctxtType->memberTypes = link;
8378 else
8379 lastLink->next = link;
8380 lastLink = link;
8381 memberType = memberType->next;
8382 }
8383 /*
8384 * The actual value is then formed by replacing any union type
8385 * definition in the ·explicit members· with the members of their
8386 * {member type definitions}, in order.
8387 */
8388 link = ctxtType->memberTypes;
8389 while (link != NULL) {
8390 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
8391 subLink = link->type->memberTypes;
8392 if (subLink != NULL) {
8393 link->type = subLink->type;
8394 if (subLink->next != NULL) {
8395 lastLink = link->next;
8396 subLink = subLink->next;
8397 prevLink = link;
8398 while (subLink != NULL) {
8399 newLink = (xmlSchemaTypeLinkPtr)
8400 xmlMalloc(sizeof(xmlSchemaTypeLink));
8401 if (newLink == NULL) {
8402 xmlSchemaPErrMemory(ctxt, "allocating a type link",
8403 NULL);
8404 return (-1);
8405 }
8406 newLink->type = memberType;
8407 prevLink->next = newLink;
8408 prevLink = newLink;
8409 newLink->next = lastLink;
8410
8411 subLink = subLink->next;
8412 }
8413 }
8414 }
8415 }
8416 link = link->next;
8417 }
8418
8419 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00008420}
8421
Daniel Veillard4255d502002-04-16 15:50:10 +00008422/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008423 * xmlSchemaIsDerivedFromBuiltInType:
8424 * @ctxt: the schema parser context
8425 * @type: the type definition
8426 * @valType: the value type
8427 *
8428 *
8429 * Returns 1 if the type has the given value type, or
8430 * is derived from such a type.
8431 */
William M. Brack803812b2004-06-03 02:11:24 +00008432static int
Daniel Veillard3646d642004-06-02 19:19:14 +00008433xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
8434 xmlSchemaTypePtr type, int valType)
8435{
8436 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008437 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00008438 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008439 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00008440 return(1);
8441 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
8442 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
8443 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
8444 ((xmlSchemaAttributePtr) type)->subtypes, valType));
8445 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
8446 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
8447 if (type->baseType != NULL)
8448 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
8449 valType));
8450 } else if ((type->subtypes != NULL) &&
8451 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
8452 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
8453 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
8454 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
8455 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
8456 valType));
8457 }
8458
8459 return (0);
8460}
8461
8462/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00008463 * xmlSchemaIsDerivedFromBuiltInType:
8464 * @type: the simpleType definition
8465 *
8466 * Returns the primitive type of the given type or
8467 * NULL in case of error.
8468 */
8469static xmlSchemaTypePtr
8470xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
8471{
8472 while (type != NULL) {
8473 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
8474 return (type);
8475 type = type->baseType;
8476 }
8477
8478 return (NULL);
8479}
8480
8481
8482/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008483 * xmlSchemaBuildAttributeUsesOwned:
8484 * @ctxt: the schema parser context
8485 * @type: the complex type definition
8486 * @cur: the attribute declaration list
8487 * @lastUse: the top of the attribute use list
8488 *
8489 * Builds the attribute uses list on the given complex type.
8490 * This one is supposed to be called by
8491 * xmlSchemaBuildAttributeValidation only.
8492 */
8493static int
8494xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
8495 xmlSchemaAttributePtr cur,
8496 xmlSchemaAttributeLinkPtr *uses,
8497 xmlSchemaAttributeLinkPtr *lastUse)
8498{
8499 xmlSchemaAttributeLinkPtr tmp;
8500 while (cur != NULL) {
8501 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
8502 /*
8503 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
8504 * to by the ·actual value·s of the ref [attribute] of the
8505 * <attributeGroup> [children], if any."
8506 */
8507 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
8508 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
8509 lastUse) == -1) {
8510 return (-1);
8511 }
8512 } else {
8513 /* W3C: "1 The set of attribute uses corresponding to the
8514 * <attribute> [children], if any."
8515 */
8516 tmp = (xmlSchemaAttributeLinkPtr)
8517 xmlMalloc(sizeof(xmlSchemaAttributeLink));
8518 if (tmp == NULL) {
8519 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
8520 return (-1);
8521 }
8522 tmp->attr = cur;
8523 tmp->next = NULL;
8524 if (*uses == NULL)
8525 *uses = tmp;
8526 else
8527 (*lastUse)->next = tmp;
8528 *lastUse = tmp;
8529 }
8530 cur = cur->next;
8531 }
8532 return (0);
8533}
8534
Daniel Veillard50355f02004-06-08 17:52:16 +00008535/**
8536 * xmlSchemaCloneWildcardNsConstraints:
8537 * @ctxt: the schema parser context
8538 * @dest: the destination wildcard
8539 * @source: the source wildcard
8540 *
8541 * Clones the namespace constraints of source
8542 * and assignes them to dest.
8543 * Returns -1 on internal error, 0 otherwise.
8544 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008545static int
8546xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
8547 xmlSchemaWildcardPtr *dest,
8548 xmlSchemaWildcardPtr source)
8549{
8550 xmlSchemaWildcardNsPtr cur, tmp, last;
8551
8552 if ((source == NULL) || (*dest == NULL))
8553 return(-1);
8554 (*dest)->any = source->any;
8555 cur = source->nsSet;
8556 last = NULL;
8557 while (cur != NULL) {
8558 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8559 if (tmp == NULL)
8560 return(-1);
8561 tmp->value = cur->value;
8562 if (last == NULL)
8563 (*dest)->nsSet = tmp;
8564 else
8565 last->next = tmp;
8566 last = tmp;
8567 cur = cur->next;
8568 }
8569 if ((*dest)->negNsSet != NULL)
8570 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
8571 if (source->negNsSet != NULL) {
8572 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8573 if ((*dest)->negNsSet == NULL)
8574 return(-1);
8575 (*dest)->negNsSet->value = source->negNsSet->value;
8576 } else
8577 (*dest)->negNsSet = NULL;
8578 return(0);
8579}
8580
Daniel Veillard50355f02004-06-08 17:52:16 +00008581/**
8582 * xmlSchemaUnionWildcards:
8583 * @ctxt: the schema parser context
8584 * @completeWild: the first wildcard
8585 * @curWild: the second wildcard
8586 *
8587 * Unions the namespace constraints of the given wildcards.
8588 * @completeWild will hold the resulting union.
8589 * Returns a positive error code on failure, -1 in case of an
8590 * internal error, 0 otherwise.
8591 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008592static int
8593xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
8594 xmlSchemaWildcardPtr completeWild,
8595 xmlSchemaWildcardPtr curWild)
8596{
8597 xmlSchemaWildcardNsPtr cur, curB, tmp;
8598
8599 /*
8600 * 1 If O1 and O2 are the same value, then that value must be the
8601 * value.
8602 */
8603 if ((completeWild->any == curWild->any) &&
8604 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8605 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8606
8607 if ((completeWild->negNsSet == NULL) ||
8608 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8609
8610 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008611 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008612
8613 /*
8614 * Check equality of sets.
8615 */
8616 cur = completeWild->nsSet;
8617 while (cur != NULL) {
8618 found = 0;
8619 curB = curWild->nsSet;
8620 while (curB != NULL) {
8621 if (cur->value == curB->value) {
8622 found = 1;
8623 break;
8624 }
8625 curB = curB->next;
8626 }
8627 if (!found)
8628 break;
8629 cur = cur->next;
8630 }
8631 if (found)
8632 return(0);
8633 } else
8634 return(0);
8635 }
8636 }
8637 /*
8638 * 2 If either O1 or O2 is any, then any must be the value
8639 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008640 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008641 if (completeWild->any == 0) {
8642 completeWild->any = 1;
8643 if (completeWild->nsSet != NULL) {
8644 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8645 completeWild->nsSet = NULL;
8646 }
8647 if (completeWild->negNsSet != NULL) {
8648 xmlFree(completeWild->negNsSet);
8649 completeWild->negNsSet = NULL;
8650 }
8651 }
Daniel Veillard50355f02004-06-08 17:52:16 +00008652 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008653 }
8654 /*
8655 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
8656 * then the union of those sets must be the value.
8657 */
8658 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8659 int found;
8660 xmlSchemaWildcardNsPtr start;
8661
8662 cur = curWild->nsSet;
8663 start = completeWild->nsSet;
8664 while (cur != NULL) {
8665 found = 0;
8666 curB = start;
8667 while (curB != NULL) {
8668 if (cur->value == curB->value) {
8669 found = 1;
8670 break;
8671 }
8672 curB = curB->next;
8673 }
8674 if (!found) {
8675 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8676 if (tmp == NULL)
8677 return (-1);
8678 tmp->value = cur->value;
8679 tmp->next = completeWild->nsSet;
8680 completeWild->nsSet = tmp;
8681 }
8682 cur = cur->next;
8683 }
8684
8685 return(0);
8686 }
8687 /*
8688 * 4 If the two are negations of different values (namespace names
8689 * or ·absent·), then a pair of not and ·absent· must be the value.
8690 */
8691 if ((completeWild->negNsSet != NULL) &&
8692 (curWild->negNsSet != NULL) &&
8693 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
8694 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00008695
8696 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008697 }
8698 /*
8699 * 5.
8700 */
8701 if (((completeWild->negNsSet != NULL) &&
8702 (completeWild->negNsSet->value != NULL) &&
8703 (curWild->nsSet != NULL)) ||
8704 ((curWild->negNsSet != NULL) &&
8705 (curWild->negNsSet->value != NULL) &&
8706 (completeWild->nsSet != NULL))) {
8707
8708 int nsFound, absentFound = 0;
8709
8710 if (completeWild->nsSet != NULL) {
8711 cur = completeWild->nsSet;
8712 curB = curWild->negNsSet;
8713 } else {
8714 cur = curWild->nsSet;
8715 curB = completeWild->negNsSet;
8716 }
8717 nsFound = 0;
8718 while (cur != NULL) {
8719 if (cur->value == NULL)
8720 absentFound = 1;
8721 else if (cur->value == curB->value)
8722 nsFound = 1;
8723 if (nsFound && absentFound)
8724 break;
8725 cur = cur->next;
8726 }
8727
8728 if (nsFound && absentFound) {
8729 /*
8730 * 5.1 If the set S includes both the negated namespace
8731 * name and ·absent·, then any must be the value.
8732 */
8733 completeWild->any = 1;
8734 if (completeWild->nsSet != NULL) {
8735 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8736 completeWild->nsSet = NULL;
8737 }
8738 if (completeWild->negNsSet != NULL) {
8739 xmlFree(completeWild->negNsSet);
8740 completeWild->negNsSet = NULL;
8741 }
8742 } else if (nsFound && (!absentFound)) {
8743 /*
8744 * 5.2 If the set S includes the negated namespace name
8745 * but not ·absent·, then a pair of not and ·absent· must
8746 * be the value.
8747 */
8748 if (completeWild->nsSet != NULL) {
8749 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8750 completeWild->nsSet = NULL;
8751 }
8752 if (completeWild->negNsSet == NULL) {
8753 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8754 if (completeWild->negNsSet == NULL)
8755 return (-1);
8756 }
8757 completeWild->negNsSet->value = NULL;
8758 } else if ((!nsFound) && absentFound) {
8759 /*
8760 * 5.3 If the set S includes ·absent· but not the negated
8761 * namespace name, then the union is not expressible.
8762 */
8763 xmlSchemaPErr(ctxt, completeWild->node,
8764 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008765 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008766 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008767 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008768 } else if ((!nsFound) && (!absentFound)) {
8769 /*
8770 * 5.4 If the set S does not include either the negated namespace
8771 * name or ·absent·, then whichever of O1 or O2 is a pair of not
8772 * and a namespace name must be the value.
8773 */
8774 if (completeWild->negNsSet == NULL) {
8775 if (completeWild->nsSet != NULL) {
8776 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8777 completeWild->nsSet = NULL;
8778 }
8779 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8780 if (completeWild->negNsSet == NULL)
8781 return (-1);
8782 completeWild->negNsSet->value = curWild->negNsSet->value;
8783 }
8784 }
8785 return (0);
8786 }
8787 /*
8788 * 6.
8789 */
8790 if (((completeWild->negNsSet != NULL) &&
8791 (completeWild->negNsSet->value == NULL) &&
8792 (curWild->nsSet != NULL)) ||
8793 ((curWild->negNsSet != NULL) &&
8794 (curWild->negNsSet->value == NULL) &&
8795 (completeWild->nsSet != NULL))) {
8796
8797 if (completeWild->nsSet != NULL) {
8798 cur = completeWild->nsSet;
8799 } else {
8800 cur = curWild->nsSet;
8801 }
8802 while (cur != NULL) {
8803 if (cur->value == NULL) {
8804 /*
8805 * 6.1 If the set S includes ·absent·, then any must be the
8806 * value.
8807 */
8808 completeWild->any = 1;
8809 if (completeWild->nsSet != NULL) {
8810 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8811 completeWild->nsSet = NULL;
8812 }
8813 if (completeWild->negNsSet != NULL) {
8814 xmlFree(completeWild->negNsSet);
8815 completeWild->negNsSet = NULL;
8816 }
8817 return (0);
8818 }
8819 cur = cur->next;
8820 }
8821 if (completeWild->negNsSet == NULL) {
8822 /*
8823 * 6.2 If the set S does not include ·absent·, then a pair of not
8824 * and ·absent· must be the value.
8825 */
8826 if (completeWild->nsSet != NULL) {
8827 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8828 completeWild->nsSet = NULL;
8829 }
8830 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8831 if (completeWild->negNsSet == NULL)
8832 return (-1);
8833 completeWild->negNsSet->value = NULL;
8834 }
8835 return (0);
8836 }
8837 return (0);
8838
8839}
8840
Daniel Veillard50355f02004-06-08 17:52:16 +00008841/**
8842 * xmlSchemaIntersectWildcards:
8843 * @ctxt: the schema parser context
8844 * @completeWild: the first wildcard
8845 * @curWild: the second wildcard
8846 *
8847 * Intersects the namespace constraints of the given wildcards.
8848 * @completeWild will hold the resulting intersection.
8849 * Returns a positive error code on failure, -1 in case of an
8850 * internal error, 0 otherwise.
8851 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008852static int
8853xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
8854 xmlSchemaWildcardPtr completeWild,
8855 xmlSchemaWildcardPtr curWild)
8856{
William M. Brack803812b2004-06-03 02:11:24 +00008857 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008858
8859 /*
8860 * 1 If O1 and O2 are the same value, then that value must be the
8861 * value.
8862 */
8863 if ((completeWild->any == curWild->any) &&
8864 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8865 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8866
8867 if ((completeWild->negNsSet == NULL) ||
8868 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8869
8870 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008871 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008872
8873 /*
8874 * Check equality of sets.
8875 */
8876 cur = completeWild->nsSet;
8877 while (cur != NULL) {
8878 found = 0;
8879 curB = curWild->nsSet;
8880 while (curB != NULL) {
8881 if (cur->value == curB->value) {
8882 found = 1;
8883 break;
8884 }
8885 curB = curB->next;
8886 }
8887 if (!found)
8888 break;
8889 cur = cur->next;
8890 }
8891 if (found)
8892 return(0);
8893 } else
8894 return(0);
8895 }
8896 }
8897 /*
8898 * 2 If either O1 or O2 is any, then the other must be the value.
8899 */
8900 if ((completeWild->any != curWild->any) && (completeWild->any)) {
8901 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8902 return(-1);
8903 return(0);
8904 }
8905 /*
8906 * 3 If either O1 or O2 is a pair of not and a value (a namespace
8907 * name or ·absent·) and the other is a set of (namespace names or
8908 * ·absent·), then that set, minus the negated value if it was in
8909 * the set, minus ·absent· if it was in the set, must be the value.
8910 */
8911 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
8912 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
8913 const xmlChar *neg;
8914
8915 if (completeWild->nsSet == NULL) {
8916 neg = completeWild->negNsSet->value;
8917 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8918 return(-1);
8919 } else
8920 neg = curWild->negNsSet->value;
8921 /*
8922 * Remove absent and negated.
8923 */
8924 prev = NULL;
8925 cur = completeWild->nsSet;
8926 while (cur != NULL) {
8927 if (cur->value == NULL) {
8928 if (prev == NULL)
8929 completeWild->nsSet = cur->next;
8930 else
8931 prev->next = cur->next;
8932 xmlFree(cur);
8933 break;
8934 }
8935 prev = cur;
8936 cur = cur->next;
8937 }
8938 if (neg != NULL) {
8939 prev = NULL;
8940 cur = completeWild->nsSet;
8941 while (cur != NULL) {
8942 if (cur->value == neg) {
8943 if (prev == NULL)
8944 completeWild->nsSet = cur->next;
8945 else
8946 prev->next = cur->next;
8947 xmlFree(cur);
8948 break;
8949 }
8950 prev = cur;
8951 cur = cur->next;
8952 }
8953 }
8954
8955 return(0);
8956 }
8957 /*
8958 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
8959 * then the intersection of those sets must be the value.
8960 */
8961 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8962 int found;
8963
8964 cur = completeWild->nsSet;
8965 prev = NULL;
8966 while (cur != NULL) {
8967 found = 0;
8968 curB = curWild->nsSet;
8969 while (curB != NULL) {
8970 if (cur->value == curB->value) {
8971 found = 1;
8972 break;
8973 }
8974 curB = curB->next;
8975 }
8976 if (!found) {
8977 if (prev == NULL)
8978 completeWild->nsSet = cur->next;
8979 else
8980 prev->next = cur->next;
8981 tmp = cur->next;
8982 xmlFree(cur);
8983 cur = tmp;
8984 continue;
8985 }
8986 prev = cur;
8987 cur = cur->next;
8988 }
8989
8990 return(0);
8991 }
8992 /* 5 If the two are negations of different namespace names,
8993 * then the intersection is not expressible
8994 */
8995 if ((completeWild->negNsSet != NULL) &&
8996 (curWild->negNsSet != NULL) &&
8997 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
8998 (completeWild->negNsSet->value != NULL) &&
8999 (curWild->negNsSet->value != NULL)) {
9000
9001 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009002 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009003 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009004 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009005 }
9006 /*
9007 * 6 If the one is a negation of a namespace name and the other
9008 * is a negation of ·absent·, then the one which is the negation
9009 * of a namespace name must be the value.
9010 */
9011 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9012 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9013 (completeWild->negNsSet->value == NULL)) {
9014 completeWild->negNsSet->value = curWild->negNsSet->value;
9015 }
9016 return(0);
9017}
9018
Daniel Veillard50355f02004-06-08 17:52:16 +00009019/**
9020 * xmlSchemaIsWildcardNsConstraintSubset:
9021 * @ctxt: the schema parser context
9022 * @wildA: the first wildcard
9023 * @wildB: the second wildcard
9024 *
9025 * Returns 1 if the namespace constraint of @wildA is an intensional
9026 * subset of @wildB, 0 otherwise.
9027 */
9028static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009029xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9030 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009031{
Daniel Veillard3646d642004-06-02 19:19:14 +00009032
Daniel Veillard50355f02004-06-08 17:52:16 +00009033 /*
9034 * Schema Component Constraint: Wildcard Subset
9035 */
9036 /*
9037 * 1 super must be any.
9038 */
9039 if (wildB->any)
9040 return (1);
9041 /*
9042 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9043 * 2.2 super must be a pair of not and the same value.
9044 */
9045 if ((wildA->negNsSet != NULL) &&
9046 (wildB->negNsSet != NULL) &&
9047 (wildA->negNsSet->value == wildA->negNsSet->value))
9048 return (1);
9049 /*
9050 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9051 */
9052 if (wildA->nsSet != NULL) {
9053 /*
9054 * 3.2.1 super must be the same set or a superset thereof.
9055 */
9056 if (wildB->nsSet != NULL) {
9057 xmlSchemaWildcardNsPtr cur, curB;
9058 int found = 0;
9059
9060 cur = wildA->nsSet;
9061 while (cur != NULL) {
9062 found = 0;
9063 curB = wildB->nsSet;
9064 while (curB != NULL) {
9065 if (cur->value == curB->value) {
9066 found = 1;
9067 break;
9068 }
9069 curB = curB->next;
9070 }
9071 if (!found)
9072 return (0);
9073 cur = cur->next;
9074 }
9075 if (found)
9076 return (1);
9077 } else if (wildB->negNsSet != NULL) {
9078 xmlSchemaWildcardNsPtr cur;
9079 /*
9080 * 3.2.2 super must be a pair of not and a namespace name or
9081 * ·absent· and that value must not be in sub's set.
9082 */
9083 cur = wildA->nsSet;
9084 while (cur != NULL) {
9085 if (cur->value == wildB->negNsSet->value)
9086 return (0);
9087 cur = cur->next;
9088 }
9089 return (1);
9090 }
9091 }
9092 return (0);
9093}
9094
9095/**
9096 * xmlSchemaBuildCompleteAttributeWildcard:
9097 * @ctxt: the schema parser context
9098 * @attrs: the attribute list
9099 * @completeWild: the resulting complete wildcard
9100 *
9101 * Returns -1 in case of an internal error, 0 otherwise.
9102 */
9103static int
9104xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9105 xmlSchemaAttributePtr attrs,
9106 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009107{
9108 while (attrs != NULL) {
9109 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9110 xmlSchemaAttributeGroupPtr group;
9111
9112 group = (xmlSchemaAttributeGroupPtr) attrs;
9113 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9114 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009115 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9116 group->attributes, &group->attributeWildcard) == -1)
9117 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009118 }
9119 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9120 }
9121 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009122 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009123 /*
9124 * Copy the first encountered wildcard as context, except for the annotation.
9125 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009126 *completeWild = xmlSchemaAddWildcard(ctxt);
9127 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9128 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9129 completeWild, group->attributeWildcard) == -1)
9130 return (-1);
9131 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009132 /*
9133 * Although the complete wildcard might not correspond to any
9134 * node in the schema, we will save this context node.
9135 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009136 (*completeWild)->node = group->attributeWildcard->node;
9137
9138 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9139 xmlSchemaFreeWildcard(*completeWild);
9140 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009141 }
9142 }
9143 }
9144 attrs = attrs->next;
9145 }
9146
Daniel Veillard50355f02004-06-08 17:52:16 +00009147 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009148}
9149
9150/**
9151 * xmlSchemaMatchesWildcardNs:
9152 * @wild: the wildcard
9153 * @ns: the namespace
9154 *
9155 *
9156 * Returns 1 if the given namespace matches the wildcard,
9157 * 0 otherwise.
9158 */
9159static int
9160xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9161{
9162 if (wild == NULL)
9163 return(0);
9164
9165 if (wild->any)
9166 return(1);
9167 else if (wild->nsSet != NULL) {
9168 xmlSchemaWildcardNsPtr cur;
9169
9170 cur = wild->nsSet;
9171 while (cur != NULL) {
9172 if (xmlStrEqual(cur->value, ns))
9173 return(1);
9174 cur = cur->next;
9175 }
9176 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9177 (!xmlStrEqual(wild->negNsSet->value, ns)))
9178 return(1);
9179
9180 return(0);
9181}
9182
9183/**
9184 * xmlSchemaBuildAttributeValidation:
9185 * @ctxt: the schema parser context
9186 * @type: the complex type definition
9187 *
9188 *
9189 * Builds the wildcard and the attribute uses on the given complex type.
9190 * Returns -1 if an internal error occurs, 0 otherwise.
9191 */
9192static int
9193xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
9194{
9195 xmlSchemaTypePtr baseType = NULL;
9196 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00009197 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009198 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009199 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00009200 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009201 xmlChar *str = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009202
Daniel Veillard01fa6152004-06-29 17:04:39 +00009203 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009204 /*
9205 * Complex Type Definition with complex content Schema Component.
9206 *
9207 * Attribute uses.
9208 */
9209 if (type->attributeUses != NULL) {
9210 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009211 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00009212 "attribute uses already builded.\n",
9213 NULL, NULL);
9214 return (-1);
9215 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009216 if (type->baseType == NULL) {
9217 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
9218 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009219 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009220 type->name, NULL);
9221 return (-1);
9222 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009223 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009224 if (baseType == anyType)
9225 baseIsAnyType = 1;
9226 /*
9227 * Inherit the attribute uses of the base type.
9228 */
9229 /*
9230 * NOTE: It is allowed to "extend" the anyType complex type.
9231 */
9232 if (!baseIsAnyType) {
9233 if (baseType != NULL) {
9234 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
9235 tmp = (xmlSchemaAttributeLinkPtr)
9236 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9237 if (tmp == NULL) {
9238 xmlSchemaPErrMemory(ctxt,
9239 "building attribute uses of complexType", NULL);
9240 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009241 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009242 tmp->attr = cur->attr;
9243 tmp->next = NULL;
9244 if (type->attributeUses == NULL) {
9245 type->attributeUses = tmp;
9246 } else
9247 lastBaseUse->next = tmp;
9248 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009249 }
9250 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009251 }
9252 if ((type->subtypes != NULL) &&
9253 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9254 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9255 attrs = type->subtypes->subtypes->attributes;
9256 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
9257 } else {
9258 /* Short hand form of the complexType. */
9259 attrs = type->attributes;
9260 }
9261 /*
9262 * Handle attribute wildcards.
9263 */
9264 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9265 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009266 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009267 /* Either we used the short hand form... */
9268 ((type->subtypes == NULL) ||
9269 /* Or complexType -> restriction/extension */
9270 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00009271 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009272 return (-1);
9273 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009274 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009275 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
9276 * create the wildcard right from the start on the complexType,
9277 * rather than on the <restriction>/<extension>.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009278 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009279 if ((type->attributeWildcard != NULL) &&
9280 /* Either we used the short hand form... */
9281 ((type->subtypes == NULL) ||
9282 /* Or complexType -> restriction/extension */
9283 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
9284 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
9285
9286 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
9287 ((baseIsAnyType) ||
9288 ((baseType != NULL) &&
9289 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9290 (baseType->attributeWildcard != NULL)))) {
9291 if (type->attributeWildcard != NULL) {
9292 /*
9293 * Union the complete wildcard with the base wildcard.
9294 */
9295 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
9296 baseType->attributeWildcard) == -1)
9297 return (-1);
9298 } else {
9299 /*
9300 * Just inherit the wildcard.
9301 */
9302 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00009303 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009304 }
9305
9306 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9307 if (type->attributeWildcard != NULL) {
9308 /*
9309 * Derivation Valid (Restriction, Complex)
9310 * 4.1 The {base type definition} must also have one.
9311 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009312 if (baseType->attributeWildcard == NULL) {
9313 xmlSchemaPCustomErr(ctxt,
9314 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
9315 NULL, type, NULL,
9316 "The type has an attribute wildcard, "
9317 "but the base type %s does not have one",
9318 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9319 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009320 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009321 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009322 type->attributeWildcard, baseType->attributeWildcard) == 0) {
9323 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009324 xmlSchemaPCustomErr(ctxt,
9325 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
9326 NULL, type, NULL,
9327 "The attribute wildcard is not a valid "
9328 "subset of the wildcard in the base type %s",
9329 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9330 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009331 return (1);
9332 }
9333 /* 4.3 Unless the {base type definition} is the ·ur-type
9334 * definition·, the complex type definition's {attribute
9335 * wildcard}'s {process contents} must be identical to or
9336 * stronger than the {base type definition}'s {attribute
9337 * wildcard}'s {process contents}, where strict is stronger
9338 * than lax is stronger than skip.
9339 */
9340 if ((type->baseType != anyType) &&
9341 (type->attributeWildcard->processContents <
9342 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009343 xmlSchemaPCustomErr(ctxt,
9344 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
9345 NULL, type, NULL,
9346 "The 'process contents' of the attribute wildcard is weaker than "
9347 "the one in the base type %s",
9348 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9349 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009350 return (1);
9351 }
9352 }
9353 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9354 /*
9355 * Derivation Valid (Extension)
9356 * At this point the type and the base have both, either
9357 * no wildcard or a wildcard.
9358 */
9359 if ((baseType->attributeWildcard != NULL) &&
9360 (baseType->attributeWildcard != type->attributeWildcard)) {
9361 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009362 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009363 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009364 xmlSchemaPCustomErr(ctxt,
9365 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
9366 NULL, type, NULL,
9367 "The attribute wildcard is not a valid "
9368 "superset of the one in the base type %s",
9369 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9370 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009371 return (1);
9372 }
9373 }
9374 }
9375
Daniel Veillard3646d642004-06-02 19:19:14 +00009376 /*
9377 * Gather attribute uses defined by this type.
9378 */
9379 if (attrs != NULL) {
9380 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
9381 &uses, &lastUse) == -1) {
9382 return (-1);
9383 }
9384 }
9385 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
9386 * "Two distinct attribute declarations in the {attribute uses} must
9387 * not have identical {name}s and {target namespace}s."
9388 *
9389 * For "extension" this is done further down.
9390 */
9391 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
9392 cur = uses;
9393 while (cur != NULL) {
9394 tmp = cur->next;
9395 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009396 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9397 xmlSchemaGetAttrName(tmp->attr))) &&
9398 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9399 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
9400
9401 xmlSchemaPAttrUseErr(ctxt,
9402 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9403 NULL, type, NULL, cur->attr,
9404 "Duplicate attribute use %s specified",
9405 xmlSchemaFormatNsUriLocal(&str,
9406 xmlSchemaGetAttrTargetNsURI(tmp->attr),
9407 xmlSchemaGetAttrName(tmp->attr))
9408 );
9409 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009410 break;
9411 }
9412 tmp = tmp->next;
9413 }
9414 cur = cur->next;
9415 }
9416 }
9417 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9418 /*
9419 * Derive by restriction.
9420 */
9421 if (baseIsAnyType) {
9422 type->attributeUses = uses;
9423 } else {
9424 int found;
9425
9426 cur = uses;
9427 while (cur != NULL) {
9428 found = 0;
9429 base = type->attributeUses;
9430 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009431 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9432 xmlSchemaGetAttrName(base->attr)) &&
9433 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
9434 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009435
Daniel Veillardc0826a72004-08-10 14:17:33 +00009436 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00009437 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
9438 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9439 /*
9440 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +00009441 */
9442 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00009443 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009444 NULL, type, NULL, cur->attr,
9445 "The 'optional' use is inconsistent with a matching "
9446 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009447 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
9448 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
9449 /*
9450 * derivation-ok-restriction 3
9451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009452 xmlSchemaPCustomErr(ctxt,
9453 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
9454 NULL, type, NULL,
9455 "A matching attribute use for the 'required' "
9456 "attribute use %s of the base type is missing",
9457 xmlSchemaFormatNsUriLocal(&str,
9458 xmlSchemaGetAttrTargetNsURI(base->attr),
9459 xmlSchemaGetAttrName(base->attr)));
9460 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00009461 } else {
9462 /*
9463 * Override the attribute use.
9464 */
9465 base->attr = cur->attr;
9466 }
9467 /*
9468 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00009469 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00009470 */
9471 break;
9472 }
9473 base = base->next;
9474 }
9475
9476 if (!found) {
9477 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9478 /*
9479 * derivation-ok-restriction 2.2
9480 */
9481 if ((type->attributeWildcard != NULL) &&
9482 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
9483 cur->attr->targetNamespace))
9484 found = 1;
9485
9486 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009487 xmlSchemaPAttrUseErr(ctxt,
9488 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
9489 NULL, type, NULL, cur->attr,
9490 "Neither a matching attribute use, "
9491 "nor a matching wildcard in the base type does exist",
9492 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00009493 } else {
9494 /*
9495 * Add the attribute use.
9496 *
9497 * Note that this may lead to funny derivation error reports, if
9498 * multiple equal attribute uses exist; but this is not
9499 * allowed anyway, and it will be reported beforehand.
9500 */
9501 tmp = cur;
9502 if (prev != NULL)
9503 prev->next = cur->next;
9504 else
9505 uses = cur->next;
9506 cur = cur->next;
9507 if (type->attributeUses == NULL) {
9508 type->attributeUses = tmp;
9509 } else
9510 lastBaseUse->next = tmp;
9511 lastBaseUse = tmp;
9512
9513 continue;
9514 }
9515 }
9516 }
9517 prev = cur;
9518 cur = cur->next;
9519 }
9520 if (uses != NULL)
9521 xmlSchemaFreeAttributeUseList(uses);
9522 }
9523 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9524 /*
9525 * The spec allows only appending, and not other kinds of extensions.
9526 *
9527 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
9528 */
9529 if (uses != NULL) {
9530 if (type->attributeUses == NULL) {
9531 type->attributeUses = uses;
9532 } else
9533 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009534 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009535 } else {
9536 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00009537 * Derive implicitely from the ur-type.
9538 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009539 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00009540 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009541 /*
9542 * 3.4.6 -> Complex Type Definition Properties Correct
9543 */
9544 if (type->attributeUses != NULL) {
9545 cur = type->attributeUses;
9546 prev = NULL;
9547 while (cur != NULL) {
9548 /*
9549 * 4. Two distinct attribute declarations in the {attribute uses} must
9550 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00009551 *
Daniel Veillard3646d642004-06-02 19:19:14 +00009552 * Note that this was already done for "restriction" and types derived from
9553 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00009554 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009555 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9556 tmp = cur->next;
9557 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009558 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9559 xmlSchemaGetAttrName(tmp->attr))) &&
9560 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9561 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009562
Daniel Veillardc0826a72004-08-10 14:17:33 +00009563 xmlSchemaPAttrUseErr(ctxt,
9564 XML_SCHEMAP_CT_PROPS_CORRECT_4,
9565 NULL, type, NULL, tmp->attr,
9566 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009567 break;
9568 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009569 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009570 }
9571 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009572 /*
9573 * 5. Two distinct attribute declarations in the {attribute uses} must
9574 * not have {type definition}s which are or are derived from ID.
9575 */
9576 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00009577 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009578 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009579 xmlSchemaPAttrUseErr(ctxt,
9580 XML_SCHEMAP_CT_PROPS_CORRECT_5,
9581 NULL, type, NULL, cur->attr,
9582 "There must not exist more than one attribute use, "
9583 "declared of type 'ID' or derived from it",
9584 NULL);
9585 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +00009586 }
Daniel Veillard3646d642004-06-02 19:19:14 +00009587 id = cur;
9588 }
9589 /*
9590 * Remove "prohibited" attribute uses. The reason this is done at this late
9591 * stage is to be able to catch dublicate attribute uses. So we had to keep
9592 * prohibited uses in the list as well.
9593 */
9594 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
9595 tmp = cur;
9596 if (prev == NULL)
9597 type->attributeUses = cur->next;
9598 else
9599 prev->next = cur->next;
9600 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00009601 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00009602 } else {
9603 prev = cur;
9604 cur = cur->next;
9605 }
9606 }
9607 }
9608 /*
9609 * TODO: This check should be removed if we are 100% sure of
9610 * the base type attribute uses already being built.
9611 */
9612 if ((baseType != NULL) && (!baseIsAnyType) &&
9613 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9614 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
9615 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009616 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009617 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009618 baseType->name, NULL);
9619 }
9620 return (0);
9621}
9622
9623/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009624 * xmlSchemaTypeFinalContains:
9625 * @schema: the schema
9626 * @type: the type definition
9627 * @final: the final
9628 *
9629 * Evaluates if a type definition contains the given "final".
9630 * This does take "finalDefault" into account as well.
9631 *
9632 * Returns 1 if the type does containt the given "final",
9633 * 0 otherwise.
9634 */
9635static int
9636xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
9637{
9638 int tfinal = final, tflags = type->flags;
9639
9640 if (type == NULL)
9641 return (0);
9642 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
9643 switch (final) {
9644 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
9645 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9646 break;
9647 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
9648 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9649 break;
9650 case XML_SCHEMAS_TYPE_FINAL_LIST:
9651 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
9652 break;
9653 case XML_SCHEMAS_TYPE_FINAL_UNION:
9654 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
9655 break;
9656 }
9657 tflags = schema->flags;
9658 }
9659 if (tflags & tfinal)
9660 return (1);
9661 else
9662 return (0);
9663
9664}
9665
9666/**
9667 * xmlSchemaGetUnionSimpleTypeMemberTypes:
9668 * @type: the Union Simple Type
9669 *
9670 * Returns a list of member types of @type if existing,
9671 * returns NULL otherwise.
9672 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009673static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00009674xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
9675{
9676 while (type != NULL) {
9677 if (type->memberTypes != NULL)
9678 return (type->memberTypes);
9679 else
9680 type = type->baseType;
9681 }
9682 return (NULL);
9683}
9684
9685/**
9686 * xmlSchemaGetListSimpleTypeItemType:
9687 * @type: the simple type definition
9688 *
9689 * Returns the item type definition of the list simple type.
9690 */
9691static xmlSchemaTypePtr
9692xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
9693{
9694 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
9695 return (NULL);
9696 /*
9697 * Note: In libxml2, the built-in types do not reflect
9698 * the datatype hierarchy (yet?) - we have to treat them
9699 * in a special way.
9700 */
9701 if (type->type == XML_SCHEMA_TYPE_BASIC)
9702 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
9703 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
9704 /* 1 If the <list> alternative is chosen, then the type
9705 * definition ·resolved· to by the ·actual value· of the
9706 * itemType [attribute] of <list>, if present, otherwise
9707 * the type definition corresponding to the <simpleType>
9708 * among the [children] of <list>.
9709 */
9710 return (type->subtypes->subtypes);
9711 else {
9712 /* 2 If the <restriction> option is chosen, then the
9713 * {item type definition} of the {base type definition}.
9714 */
9715 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
9716 }
9717}
9718
9719/**
9720 * xmlSchemaCheckCOSSTDerivedOK:
9721 * @type: the derived simple type definition
9722 * @baseType: the base type definition
9723 *
9724 * Checks wheter @type can be validly
9725 * derived from @baseType.
9726 *
9727 * Returns 0 on success, an positive error code otherwise.
9728 */
9729static int
9730xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
9731 xmlSchemaTypePtr type,
9732 xmlSchemaTypePtr baseType,
9733 int subset)
9734{
9735 /*
9736 * Schema Component Constraint: Type Derivation OK (Simple)
9737 *
9738 *
9739 * 1 They are the same type definition.
9740 * TODO: The identy check might have to be more complex than this.
9741 */
9742 if (type == baseType)
9743 return (0);
9744 /*
9745 * 2.1 restriction is not in the subset, or in the {final}
9746 * of its own {base type definition};
9747 */
9748 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
9749 (xmlSchemaTypeFinalContains(schema,
9750 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
9751 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
9752 }
9753 /* 2.2 */
9754 if (type->baseType == baseType) {
9755 /*
9756 * 2.2.1 D's ·base type definition· is B.
9757 */
9758 return (0);
9759 }
9760 /*
9761 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
9762 * and is validly derived from B given the subset, as defined by this
9763 * constraint.
9764 */
9765 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
9766 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
9767 return (0);
9768 }
9769 /*
9770 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
9771 * definition·.
9772 */
9773 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
9774 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
9775 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
9776 return (0);
9777 }
9778 /*
9779 * 2.2.4 B's {variety} is union and D is validly derived from a type
9780 * definition in B's {member type definitions} given the subset, as
9781 * defined by this constraint.
9782 *
9783 * NOTE: This seems not to involve built-in types, since there is no
9784 * built-in Union Simple Type.
9785 */
9786 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9787 xmlSchemaTypeLinkPtr cur;
9788
9789 cur = baseType->memberTypes;
9790 while (cur != NULL) {
9791 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
9792 cur->type, subset) == 0)
9793 return (0);
9794 cur = cur->next;
9795 }
9796 }
9797
9798 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
9799}
9800
9801
9802/**
9803 * xmlSchemaCheckSTPropsCorrect:
9804 * @ctxt: the schema parser context
9805 * @type: the simple type definition
9806 *
9807 * Checks st-props-correct.
9808 *
9809 * Returns 0 if the properties are correct,
9810 * if not, a positive error code and -1 on internal
9811 * errors.
9812 */
9813static int
9814xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
9815 xmlSchemaTypePtr type)
9816{
9817 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
9818 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009819 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009820
Daniel Veillardc0826a72004-08-10 14:17:33 +00009821 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009822 /*
9823 * Schema Component Constraint: Simple Type Definition Properties Correct
9824 *
9825 * NOTE: This is somehow redundant, since we actually built a simple type
9826 * to have all the needed information; this acts as an self test.
9827 */
9828 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9829 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9830 /*
9831 * TODO: 1 The values of the properties of a simple type definition must be as
9832 * described in the property tableau in Datatype definition, modulo the
9833 * impact of Missing Sub-components (§5.3).
9834 */
9835 /* Base type: If the datatype has been ·derived· by ·restriction·
9836 * then the Simple Type Definition component from which it is ·derived·,
9837 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
9838 */
9839 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009840 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009841 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009842 NULL, type, NULL,
9843 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009844 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9845 }
9846 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
9847 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
9848 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009849 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009850 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009851 NULL, type, NULL,
9852 "The base type %s is not a simple type",
9853 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9854 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009855 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9856 }
9857 if ((baseType != anySimpleType) &&
9858 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009859 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009860 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009861 NULL, type, NULL,
9862 "A type, derived by list or union, must have"
9863 "the simple ur-type definition as base type, not %s",
9864 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9865 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009866 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9867 }
9868 /*
9869 * Variety: One of {atomic, list, union}.
9870 */
9871 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9872 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
9873 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009874 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009875 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009876 NULL, type, NULL,
9877 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009878 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9879 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009880 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009881
9882 /*
9883 * 2 All simple type definitions must be derived ultimately from the ·simple
9884 * ur-type definition (so· circular definitions are disallowed). That is, it
9885 * must be possible to reach a built-in primitive datatype or the ·simple
9886 * ur-type definition· by repeatedly following the {base type definition}.
9887 */
9888 baseType = type->baseType;
9889 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
9890 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9891 xmlSchemaTypeFixup(baseType, ctxt, NULL);
9892 if (baseType == anySimpleType)
9893 break;
9894 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009895 xmlSchemaPCustomErr(ctxt,
9896 XML_SCHEMAP_ST_PROPS_CORRECT_2,
9897 NULL, type, NULL,
9898 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009899 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
9900 }
9901 baseType = baseType->baseType;
9902 }
9903 /*
9904 * 3 The {final} of the {base type definition} must not contain restriction.
9905 */
9906 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
9907 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009908 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009909 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009910 NULL, type, NULL,
9911 "The 'final' of its base type %s must not contain "
9912 "'restriction'",
9913 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9914 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009915 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
9916 }
9917 return (0);
9918}
9919
9920/**
9921 * xmlSchemaCheckDerivationValidSimpleRestriction:
9922 * @ctxt: the schema parser context
9923 * @type: the simple type definition
9924 *
9925 * Checks if the given @type (simpleType) is derived
9926 * validly by restriction.
9927 *
9928 * Returns -1 on internal errors, 0 if the type is validly derived,
9929 * a positive error code otherwise.
9930 */
9931static int
9932xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009933 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009934{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009935 xmlChar *str = NULL;
9936
9937 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009938
9939 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
9940 xmlSchemaPErr(ctxt, type->node,
9941 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009942 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
9943 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009944 type->name, NULL);
9945 return (-1);
9946 }
9947
9948 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9949 xmlSchemaTypePtr primitive;
9950 /*
9951 * 1.1 The {base type definition} must be an atomic simple
9952 * type definition or a built-in primitive datatype.
9953 */
9954 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009955 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009956 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009957 NULL, type, NULL,
9958 "The base type %s is not an atomic simple type",
9959 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9960 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009961 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
9962 }
9963 /* 1.2 The {final} of the {base type definition} must not contain
9964 * restriction.
9965 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009966 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009967 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
9968 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009969 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009970 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009971 NULL, type, NULL,
9972 "The final of its base type %s must not contain 'restriction'",
9973 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9974 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
9976 }
9977
9978 /*
9979 * 1.3.1 DF must be an allowed constraining facet for the {primitive
9980 * type definition}, as specified in the appropriate subsection of 3.2
9981 * Primitive datatypes.
9982 */
9983 if (type->facets != NULL) {
9984 xmlSchemaFacetPtr facet;
9985 int ok = 1;
9986
9987 primitive = xmlSchemaGetPrimitiveType(type);
9988 if (primitive == NULL) {
9989 xmlSchemaPErr(ctxt, type->node,
9990 XML_ERR_INTERNAL_ERROR,
9991 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009992 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009993 type->name, NULL);
9994 return (-1);
9995 }
9996 facet = type->facets;
9997 do {
9998 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009999 ok = 0;
10000 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010001 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010002 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010003 }
10004 facet = facet->next;
10005 } while (facet != NULL);
10006 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010007 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010008 }
10009 /*
10010 * TODO: 1.3.2 (facet derivation)
10011 */
10012 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10013 xmlSchemaTypePtr itemType = NULL;
10014
10015 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10016 if (itemType == NULL) {
10017 xmlSchemaPErr(ctxt, type->node,
10018 XML_ERR_INTERNAL_ERROR,
10019 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010020 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010021 type->name, NULL);
10022 return (-1);
10023 }
10024 /*
10025 * 2.1 The {item type definition} must have a {variety} of atomic or
10026 * union (in which case all the {member type definitions}
10027 * must be atomic).
10028 */
10029 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10030 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010031 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010032 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010033 NULL, type, NULL,
10034 "The item type %s must have a variety of atomic or union",
10035 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10036 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010037 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10038 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10039 xmlSchemaTypeLinkPtr member;
10040
10041 member = itemType->memberTypes;
10042 while (member != NULL) {
10043 if ((member->type->flags &
10044 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010045 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010046 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010047 NULL, type, NULL,
10048 "The item type is a union type, but the "
10049 "member type %s of this item type is not atomic",
10050 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10051 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010052 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10053 }
10054 member = member->next;
10055 }
10056 }
10057
10058 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10059 xmlSchemaFacetPtr facet;
10060 /*
10061 * This is the case if we have: <simpleType><list ..
10062 */
10063 /*
10064 * 2.3.1
10065 * 2.3.1.1 The {final} of the {item type definition} must not
10066 * contain list.
10067 */
10068 if (xmlSchemaTypeFinalContains(ctxt->schema,
10069 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010070 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010071 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010072 NULL, type, NULL,
10073 "The final of its item type %s must not contain 'list'",
10074 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10075 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010076 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10077 }
10078 /*
10079 * 2.3.1.2 The {facets} must only contain the whiteSpace
10080 * facet component.
10081 */
10082 if (type->facets != NULL) {
10083 facet = type->facets;
10084 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010085 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10086 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010087 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010088 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010089 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10090 }
10091 facet = facet->next;
10092 } while (facet != NULL);
10093 }
10094 /*
10095 * TODO: Datatypes states:
10096 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10097 * whose ·lexical space· allows space (such as string or anyURI)or
10098 * a ·union· datatype any of whose {member type definitions}'s
10099 * ·lexical space· allows space.
10100 */
10101 } else {
10102 /*
10103 * This is the case if we have: <simpleType><restriction ...
10104 */
10105 /*
10106 * 2.3.2
10107 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10108 */
10109 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010110 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010111 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010112 NULL, type, NULL,
10113 "The base type %s must be a list type",
10114 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10115 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010116 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10117 }
10118 /*
10119 * 2.3.2.2 The {final} of the {base type definition} must not
10120 * contain restriction.
10121 */
10122 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10123 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010124 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010125 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010126 NULL, type, NULL,
10127 "The final of the base type %s must not contain 'restriction'",
10128 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10129 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010130 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10131 }
10132 /*
10133 * 2.3.2.3 The {item type definition} must be validly derived
10134 * from the {base type definition}'s {item type definition} given
10135 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10136 */
10137 {
10138 xmlSchemaTypePtr baseItemType;
10139
10140 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
10141 if (baseItemType == NULL) {
10142 xmlSchemaPErr(ctxt, type->node,
10143 XML_ERR_INTERNAL_ERROR,
10144 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010145 "List simple type '%s': Failed to "
10146 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010147 type->name, type->baseType->name);
10148 return (-1);
10149 }
10150 if ((itemType != baseItemType) &&
10151 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
10152 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010153 xmlChar *strBIT = NULL, *strBT = NULL;
10154 xmlSchemaPCustomErrExt(ctxt,
10155 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
10156 NULL, type, NULL,
10157 "The item type %s is not validly derived from the "
10158 "item type %s of the base type %s",
10159 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
10160 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
10161 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10162
10163 FREE_AND_NULL(str)
10164 FREE_AND_NULL(strBIT)
10165 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010166 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
10167 }
10168 }
10169
10170 if (type->facets != NULL) {
10171 xmlSchemaFacetPtr facet;
10172 int ok = 1;
10173 /*
10174 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
10175 * and enumeration facet components are allowed among the {facets}.
10176 */
10177 facet = type->facets;
10178 do {
10179 switch (facet->type) {
10180 case XML_SCHEMA_FACET_LENGTH:
10181 case XML_SCHEMA_FACET_MINLENGTH:
10182 case XML_SCHEMA_FACET_MAXLENGTH:
10183 case XML_SCHEMA_FACET_WHITESPACE:
10184 /*
10185 * TODO: 2.5.1.2 List datatypes
10186 * The value of ·whiteSpace· is fixed to the value collapse.
10187 */
10188 case XML_SCHEMA_FACET_PATTERN:
10189 case XML_SCHEMA_FACET_ENUMERATION:
10190 break;
10191 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010192 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010193 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010194 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010195 /*
10196 * We could return, but it's nicer to report all
10197 * invalid facets.
10198 */
10199 ok = 0;
10200 }
10201 }
10202 facet = facet->next;
10203 } while (facet != NULL);
10204 if (ok == 0)
10205 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
10206 /*
10207 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
10208 * is a facet of the same kind in the {facets} of the {base type
10209 * definition} (call this BF),then the DF's {value} must be a valid
10210 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
10211 */
10212 }
10213
10214
10215 }
10216 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10217 /*
10218 * 3.1 The {member type definitions} must all have {variety} of
10219 * atomic or list.
10220 */
10221 xmlSchemaTypeLinkPtr member;
10222
10223 member = type->memberTypes;
10224 while (member != NULL) {
10225 if (((member->type->flags &
10226 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10227 ((member->type->flags &
10228 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010229 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010230 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010231 NULL, type, NULL,
10232 "The member type %s is neither an atomic, nor a list type",
10233 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10234 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010235 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
10236 }
10237 member = member->next;
10238 }
10239 /*
10240 * 3.3.1 If the {base type definition} is the ·simple ur-type
10241 * definition·
10242 */
10243 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10244 /*
10245 * 3.3.1.1 All of the {member type definitions} must have a
10246 * {final} which does not contain union.
10247 */
10248 member = type->memberTypes;
10249 while (member != NULL) {
10250 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
10251 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010252 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010253 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010254 NULL, type, NULL,
10255 "The final of member type %s contains 'union'",
10256 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10257 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010258 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
10259 }
10260 member = member->next;
10261 }
10262 /*
10263 * 3.3.1.2 The {facets} must be empty.
10264 */
10265 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010266 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010267 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010268 NULL, type, NULL,
10269 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010270 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
10271 }
10272 } else {
10273 /*
10274 * 3.3.2.1 The {base type definition} must have a {variety} of union.
10275 */
10276 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010277 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010278 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010279 NULL, type, NULL,
10280 "The base type %s is not a union type",
10281 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10282 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010283 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
10284 }
10285 /*
10286 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
10287 */
10288 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10289 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010290 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010291 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010292 NULL, type, NULL,
10293 "The final of its base type %s must not contain 'restriction'",
10294 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10295 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010296 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
10297 }
10298 /*
10299 * 3.3.2.3 The {member type definitions}, in order, must be validly
10300 * derived from the corresponding type definitions in the {base
10301 * type definition}'s {member type definitions} given the empty set,
10302 * as defined in Type Derivation OK (Simple) (§3.14.6).
10303 */
10304 {
10305 xmlSchemaTypeLinkPtr baseMember;
10306
10307 /*
10308 * OPTIMIZE: if the type is restricting, it has no local defined
10309 * member types and inherits the member types of the base type;
10310 * thus a check for equality can be skipped.
10311 */
10312 /*
10313 * TODO: Even worse: I cannot see a scenario where a restricting
10314 * union simple type can have other member types as the member
10315 * types of it's base type. This check seems not necessary with
10316 * respect to the derivation process in libxml2.
10317 */
10318 if (type->memberTypes != NULL) {
10319 member = type->memberTypes;
10320 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
10321 if ((member == NULL) && (baseMember != NULL)) {
10322 xmlSchemaPErr(ctxt, type->node,
10323 XML_SCHEMAS_ERR_INTERNAL,
10324 "Internal error: "
10325 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010326 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010327 "of member types in the base type\n",
10328 type->name, NULL);
10329 }
10330 while (member != NULL) {
10331 if (baseMember == NULL) {
10332 xmlSchemaPErr(ctxt, type->node,
10333 XML_SCHEMAS_ERR_INTERNAL,
10334 "Internal error: "
10335 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010336 "(3.3.2.3), union simple type '%s', unequal number "
10337 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010338 type->name, NULL);
10339 }
10340 if ((member->type != baseMember->type) &&
10341 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
10342 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010343 xmlChar *strBMT = NULL, *strBT = NULL;
10344
10345 xmlSchemaPCustomErrExt(ctxt,
10346 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
10347 NULL, type, NULL,
10348 "The member type %s is not validly derived from its "
10349 "corresponding member type %s of the base type %s",
10350 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
10351 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
10352 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10353 FREE_AND_NULL(str)
10354 FREE_AND_NULL(strBMT)
10355 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010356 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
10357 }
10358 member = member->next;
10359 baseMember = baseMember->next;
10360 }
10361 }
10362 }
10363 /*
10364 * 3.3.2.4 Only pattern and enumeration facet components are
10365 * allowed among the {facets}.
10366 */
10367 if (type->facets != NULL) {
10368 xmlSchemaFacetPtr facet;
10369 int ok = 1;
10370
10371 facet = type->facets;
10372 do {
10373 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
10374 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010375 xmlSchemaPIllegalFacetListUnionErr(ctxt,
10376 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
10377 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010378 ok = 0;
10379 }
10380 facet = facet->next;
10381 } while (facet != NULL);
10382 if (ok == 0)
10383 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
10384
10385 }
10386 /*
10387 * TODO: 3.3.2.5 (facet derivation)
10388 */
10389 }
10390 }
10391
10392 return (0);
10393}
10394
10395/**
10396 * xmlSchemaCheckSRCSimpleType:
10397 * @ctxt: the schema parser context
10398 * @type: the simple type definition
10399 *
10400 * Checks crc-simple-type constraints.
10401 *
10402 * Returns 0 if the constraints are satisfied,
10403 * if not a positive error code and -1 on internal
10404 * errors.
10405 */
10406static int
10407xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
10408 xmlSchemaTypePtr type)
10409{
10410 /*
10411 * NOTE: src-simple-type 2-4 are redundant, since the checks
10412 * were are done for the corresponding <restriction>, <list> and <union>
10413 * elements, but W3C wants a <simpleType> error as well, so it gets one.
10414 * Maby this can be skipped in the future, if we get sure it's not needed.
10415 */
10416 if (type->subtypes == NULL) {
10417 xmlSchemaPErr(ctxt, type->node,
10418 XML_SCHEMAS_ERR_INTERNAL,
10419 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010420 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010421 type->name, NULL);
10422 return (-1);
10423 }
10424 /*
10425 * src-simple-type.1 The corresponding simple type definition, if any,
10426 * must satisfy the conditions set out in Constraints on Simple Type
10427 * Definition Schema Components (§3.14.6).
10428 */
10429 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
10430 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
10431 /*
10432 * TODO: Removed this, since it got annoying to get an
10433 * extra error report, if anything failed until now.
10434 * Enable this if needed.
10435 */
10436 /*
10437 xmlSchemaPErr(ctxt, type->node,
10438 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010439 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010440 "on simple type definitions.\n",
10441 type->name, NULL);
10442 */
10443 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
10444 }
10445
10446 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
10447 /*
10448 * src-simple-type.2 If the <restriction> alternative is chosen,
10449 * either it must have a base [attribute] or a <simpleType> among its
10450 * [children], but not both.
10451 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010452 /*
10453 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
10454 * NOTE: This was removed, since this will be already handled
10455 * in the parse function for <restriction>.
10456 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010457 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
10458 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
10459 * an itemType [attribute] or a <simpleType> among its [children],
10460 * but not both.
10461 * NOTE: baseType is set to the local simple type definiton,
10462 * if existent, at parse time. This is a hack and not nice.
10463 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010464 /*
10465 * TODO: Remove this, and add the check to the parse function of <list>.
10466 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010467 if (((type->subtypes->base == NULL) &&
10468 (type->baseType == NULL)) ||
10469 ((type->subtypes->base != NULL) &&
10470 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010471 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010472 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010473 NULL, type, NULL,
10474 "Either the attribute 'itemType' or the <simpleType> child "
10475 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010476 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
10477 }
10478
10479
10480 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
10481 xmlSchemaTypeLinkPtr member;
10482 xmlSchemaTypePtr ancestor, anySimpleType;
10483
10484 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10485
10486 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
10487 * the <union> alternative is chosen, there must not be any entries
10488 * in the memberTypes [attribute] at any depth which resolve to the
10489 * component corresponding to the <simpleType>.
10490 */
10491 member = type->memberTypes;
10492 while (member != NULL) {
10493 ancestor = member->type;
10494 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
10495 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10496 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
10497 if (ancestor == anySimpleType)
10498 break;
10499 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010500 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010501 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010502 NULL, type, NULL,
10503 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010504 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
10505 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10506 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000010507 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000010508 * type as item type, which in turn has a list ST as member
10509 * type, we will assume this here as well, since this check
10510 * was not yet performed.
10511 */
10512
10513 }
10514 ancestor = ancestor->baseType;
10515 }
10516 member = member->next;
10517 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010518 }
10519
10520 return (0);
10521}
10522
William M. Brack2f2a6632004-08-20 23:09:47 +000010523#if 0 /* Not yet used code for CT schema validation */
10524static int
10525xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
10526 const xmlChar * value,
10527 xmlSchemaTypePtr type,
10528 int fireErrors)
10529{
10530 int ret;
10531 /*
10532 * 3.14.4 Simple Type Definition Validation Rules
10533 * Validation Rule: String Valid
10534 */
10535 /*
10536 * 1 It is schema-valid with respect to that definition as defined
10537 * by Datatype Valid in [XML Schemas: Datatypes].
10538 */
10539 ctxt->type = type;
10540 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, fireErrors, 1, 1);
10541 return (ret);
10542 /*
10543 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
10544 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
10545 * the string must be a ·declared entity name·.
10546 */
10547 /*
10548 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
10549 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
10550 * then every whitespace-delimited substring of the string must be a ·declared
10551 * entity name·.
10552 */
10553 /*
10554 * 2.3 otherwise no further condition applies.
10555 */
10556
10557 return (0);
10558}
10559
10560
10561static int
10562xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr ctxt,
10563 xmlSchemaElementPtr elemDecl)
10564{
10565 xmlSchemaTypePtr typeDef;
10566 if (elemDecl->value == NULL)
10567 return (0);
10568 if (elemDecl->subtypes == NULL) {
10569 xmlSchemaPCustomErr(ctxt,
10570 XML_SCHEMAS_ERR_INTERNAL,
10571 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
10572 "Internal error: xmlSchemaCheckCOSValidDefault, "
10573 "the element decl. '%s' has no type assigned", elemDecl->name);
10574 return (-1);
10575 }
10576 typeDef = elemDecl->subtypes;
10577 if ((typeDef->type == XML_SCHEMA_TYPE_SIMPLE) ||
10578 ((typeDef->type == XML_SCHEMA_TYPE_COMPLEX) &&
10579 ((typeDef->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10580 (typeDef->contentType == XML_SCHEMA_CONTENT_BASIC)))) {
10581 xmlSchemaValidCtxtPtr vctxt;
10582 xmlAttrPtr attr;
10583 int ret = 0;
10584 /*
10585 * 1 If the type definition is a simple type definition, then the string
10586 * must be ·valid· with respect to that definition as defined by String
10587 * Valid (§3.14.4).
10588 */
10589 /*
10590 * 2.2.1 If the {content type} is a simple type definition, then the
10591 * string must be ·valid· with respect to that simple type definition
10592 * as defined by String Valid (§3.14.4).
10593 */
10594 /*
10595 * TODO: ?
10596 */
10597
10598 vctxt = xmlSchemaNewValidCtxt(NULL);
10599 if (vctxt == NULL) {
10600 xmlSchemaPErr(ctxt, elemDecl->node,
10601 XML_SCHEMAS_ERR_INTERNAL,
10602 "Internal error: xmlSchemaCheckCOSValidDefault, "
10603 "creation of a new validation context failed.\n",
10604 NULL, NULL);
10605 return (-1);
10606 }
10607 /*
10608 * TODO: This won't work.
10609 */
10610 if (typeDef->type == XML_SCHEMA_TYPE_SIMPLE)
10611 ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0);
10612 if (ret > 0) {
10613 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10614 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10615 else
10616 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10617 if (ctxt != NULL) {
10618 xmlSchemaPSimpleTypeErr(ctxt,
10619 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10620 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10621 elemDecl->subtypes, NULL, elemDecl->value,
10622 NULL, NULL, NULL);
10623 return (ctxt->err);
10624 }
10625 ret = ctxt->err;
10626 } else if (ret < 0) {
10627 xmlSchemaPErr(ctxt, elemDecl->node,
10628 XML_SCHEMAS_ERR_INTERNAL,
10629 "Internal error: xmlSchemaCheckCOSValidDefault, "
10630 "while validating the default/fixed value.\n",
10631 NULL, NULL);
10632 }
10633 xmlSchemaFreeValidCtxt(vctxt);
10634 return (ret);
10635 } else {
10636 /*
10637 * Complex type.
10638 *
10639 * 2.1 its {content type} must be a simple type definition or mixed.
10640 */
10641 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10642 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC) &&
10643 (elemDecl->subtypes->contentType == XML_SCHEMA_CONTENT_MIXED)) {
10644 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10645 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
10646 "The content type must be a simple type definition or mixed.",
10647 NULL);
10648 return(ctxt->err);
10649 }
10650 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
10651 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC)) {
10652 xmlSchemaValidCtxtPtr vctxt;
10653 xmlAttrPtr attr;
10654 int ret;
10655
10656 /* TODO: Avoid creation of a new context. */
10657 vctxt = xmlSchemaNewValidCtxt(NULL);
10658 if (vctxt == NULL) {
10659 xmlSchemaPErr(ctxt, elemDecl->node,
10660 XML_SCHEMAS_ERR_INTERNAL,
10661 "Internal error: xmlSchemaCheckCOSValidDefault, "
10662 "creation of a new validation context failed.\n",
10663 NULL, NULL);
10664 return (-1);
10665 }
10666 vctxt->type = elemDecl->subtypes;
10667 ret = xmlSchemaValidateSimpleTypeValue(vctxt, elemDecl->value, 0, 1, 1);
10668 if (ret > 0) {
10669 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
10670 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
10671 else
10672 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
10673 if (ctxt != NULL) {
10674 xmlSchemaPSimpleTypeErr(ctxt,
10675 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
10676 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
10677 elemDecl->subtypes, NULL, elemDecl->value,
10678 NULL, NULL, NULL);
10679 return (ctxt->err);
10680 }
10681 ret = ctxt->err;
10682 } else if (ret < 0) {
10683 xmlSchemaPErr(ctxt, elemDecl->node,
10684 XML_SCHEMAS_ERR_INTERNAL,
10685 "Internal error: xmlSchemaCheckCOSValidDefault, "
10686 "while validating the default/fixed value.\n",
10687 NULL, NULL);
10688 }
10689 xmlSchemaFreeValidCtxt(vctxt);
10690 return (ret);
10691 } else {
10692 /*
10693 * 2.2.2 If the {content type} is mixed, then the {content type}'s
10694 * particle must be ·emptiable· as defined by Particle Emptiable
10695 * (§3.9.6).
10696 */
10697 /*
10698 * TODO: Implement this.
10699 */
10700 }
10701 }
10702
10703 return (0);
10704}
10705
10706/**
10707 * xmlSchemaGetSTContentOfCT:
10708 * @ctxt: the schema parser context
10709 * @type: the complex type definition
10710 *
10711 *
10712 * Returns the corresponding simple type for the content of
10713 * the complex type.
10714 */
10715static xmlSchemaTypePtr
10716xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
10717 xmlSchemaTypePtr type)
10718{
10719 xmlSchemaTypePtr orig = type, anyType;
10720
10721 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10722 while ((type != NULL) && (type != anyType) &&
10723 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10724 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
10725 return(type);
10726 type = type->baseType;
10727 }
10728 xmlSchemaPCustomErr(ctxt,
10729 XML_SCHEMAS_ERR_INTERNAL,
10730 NULL, orig, NULL,
10731 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
10732 "no simple type for the content of complex type '%s' could be "
10733 "computed", orig->name);
10734 return (NULL);
10735}
10736
10737
10738static xmlSchemaTypePtr
10739xmlSchemaGetContentType(xmlSchemaParserCtxtPtr ctxt,
10740 xmlSchemaTypePtr type)
10741{
10742 if (type->baseType == NULL) {
10743 xmlSchemaPCustomErr(ctxt,
10744 XML_SCHEMAS_ERR_INTERNAL,
10745 NULL, type, NULL,
10746 "Internal error: xmlSchemaGetContentType, "
10747 "the complex type '%s' has no base type", type->name);
10748 return (NULL);
10749 }
10750 if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
10751 if ((type->baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10752 ((type->baseType->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10753 (type->baseType->contentType == XML_SCHEMA_CONTENT_BASIC)) &&
10754 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
10755 /*
10756 * 1 If the type definition ·resolved· to by the ·actual value· of
10757 * the base [attribute] is a complex type definition whose own
10758 * {content type} is a simple type definition and the <restriction>
10759 * alternative is chosen
10760 */
10761
10762
10763 }
10764 } else {
10765
10766 }
10767}
10768
10769/**
10770 * xmlSchemaCheckCOSCTExtends:
10771 * @ctxt: the schema parser context
10772 * @type: the complex type definition
10773 *
10774 * Schema Component Constraint: Derivation Valid (Extension)
10775 *
10776 * Returns 0 if the constraints are satisfied, a positive
10777 * error code if not and -1 if an internal error occured.
10778 */
10779static int
10780xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
10781 xmlSchemaTypePtr type)
10782{
10783 xmlSchemaTypePtr base;
10784 /*
10785 * 1 If the {base type definition} is a complex type definition,
10786 * then all of the following must be true:
10787 */
10788 base = type->baseType;
10789 if (base == NULL) {
10790 xmlSchemaPCustomErr(ctxt,
10791 XML_SCHEMAS_ERR_INTERNAL,
10792 NULL, type, NULL,
10793 "Internal error: xmlSchemaCheckCOSCTExtends, "
10794 "the complex type '%s' has no base type", type->name);
10795 return (-1);
10796 }
10797 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
10798 /*
10799 * 1.1 The {final} of the {base type definition} must not
10800 * contain extension.
10801 */
10802 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
10803 xmlSchemaPCustomErr(ctxt,
10804 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
10805 NULL, type, NULL,
10806 "The 'final' of the base type definition "
10807 "contains extension", NULL);
10808 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
10809 }
10810 /*
10811 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
10812 * of the complex type definition itself, that is, for every attribute
10813 * use in the {attribute uses} of the {base type definition}, there
10814 * must be an attribute use in the {attribute uses} of the complex
10815 * type definition itself whose {attribute declaration} has the same
10816 * {name}, {target namespace} and {type definition} as its attribute
10817 * declaration
10818 *
10819 * NOTE: This will be already satisfied by the way the attribute uses
10820 * are extended in xmlSchemaBuildAttributeValidation; thus this check
10821 * is not needed.
10822 */
10823
10824 /*
10825 * 1.3 If it has an {attribute wildcard}, the complex type definition
10826 * must also have one, and the base type definition's {attribute
10827 * wildcard}'s {namespace constraint} must be a subset of the complex
10828 * type definition's {attribute wildcard}'s {namespace constraint},
10829 * as defined by Wildcard Subset (§3.10.6).
10830 *
10831 * This is already checked in xmlSchemaBuildAttributeValidation; thus
10832 * this check is not needed.
10833 */
10834
10835 /*
10836 * 1.4 One of the following must be true:
10837 *
10838 * 1.4.1 The {content type} of the {base type definition} and the
10839 * {content type} of the complex type definition itself must be the same
10840 * simple type definition
10841 */
10842
10843
10844
10845 } else {
10846 /*
10847 * 2 If the {base type definition} is a simple type definition,
10848 * then all of the following must be true:
10849 */
10850 /*
10851 * 2.1 The {content type} must be the same simple type definition.
10852 */
10853 /*
10854 * 2.2 The {final} of the {base type definition} must not contain
10855 * extension
10856 */
10857 }
10858
10859}
10860
10861#endif
10862
Daniel Veillard01fa6152004-06-29 17:04:39 +000010863/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010864 * xmlSchemaTypeFixup:
10865 * @typeDecl: the schema type definition
10866 * @ctxt: the schema parser context
10867 *
10868 * Fixes the content model of the type.
10869 */
10870static void
10871xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010872 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000010873{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010874 xmlSchemaTypePtr ctxtType;
10875
Daniel Veillard82bbbd42003-05-11 20:16:09 +000010876 if (typeDecl == NULL)
10877 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010878 /*
10879 * Do not allow the following types to be typefixed, prior to
10880 * the corresponding simple/complex types.
10881 */
10882 if (ctxt->ctxtType == NULL) {
10883 switch (typeDecl->type) {
10884 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10885 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10886 case XML_SCHEMA_TYPE_UNION:
10887 case XML_SCHEMA_TYPE_RESTRICTION:
10888 case XML_SCHEMA_TYPE_EXTENSION:
10889 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010890 default:
10891 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010892 }
10893 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010894 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010895 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010896 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010897 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010898 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
10899 if (typeDecl->subtypes != NULL) {
10900 if (typeDecl->subtypes->contentType ==
10901 XML_SCHEMA_CONTENT_UNKNOWN) {
10902 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
10903 NULL);
10904 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010905 typeDecl->contentType =
10906 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010907 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010908 break;
10909 }
10910 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010911 xmlSchemaTypePtr base = NULL;
10912
10913 ctxt->ctxtType->flags |=
10914 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
William M. Brack2f2a6632004-08-20 23:09:47 +000010915 if (typeDecl->baseType != NULL)
10916 base = typeDecl->baseType;
10917 else if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010918 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010919 xmlSchemaGetType(ctxt->schema, typeDecl->base,
10920 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010921 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010922 xmlSchemaPResCompAttrErr(ctxt,
10923 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000010924 NULL, NULL,
10925 (xmlNodePtr) xmlSchemaGetPropNode(typeDecl->node, "base"),
Daniel Veillardc0826a72004-08-10 14:17:33 +000010926 "base", typeDecl->base, typeDecl->baseNs,
10927 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010928 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000010929 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010930 xmlSchemaTypeFixup(base, ctxt, NULL);
10931 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010932 }
10933 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010934 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
10935 /*
10936 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000010937 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010938 /*
10939 * Content type.
10940 */
10941 if (typeDecl->subtypes == NULL)
10942 /* 1.1.1 */
10943 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10944 else if ((typeDecl->subtypes->subtypes == NULL) &&
10945 ((typeDecl->subtypes->type ==
10946 XML_SCHEMA_TYPE_ALL)
10947 || (typeDecl->subtypes->type ==
10948 XML_SCHEMA_TYPE_SEQUENCE)))
10949 /* 1.1.2 */
10950 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10951 else if ((typeDecl->subtypes->type ==
10952 XML_SCHEMA_TYPE_CHOICE)
10953 && (typeDecl->subtypes->subtypes == NULL))
10954 /* 1.1.3 */
10955 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10956 else {
10957 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010958 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000010959 XML_SCHEMA_CONTENT_ELEMENTS;
10960 }
10961 } else {
10962 /*
10963 * SimpleType restriction.
10964 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010965 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010966 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010967 break;
10968 }
10969 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010970 xmlSchemaTypePtr base = NULL;
10971 xmlSchemaContentType explicitContentType;
10972
10973 /*
10974 * An extension does exist on a complexType only.
10975 */
10976 ctxt->ctxtType->flags |=
10977 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
10978 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010979 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010980 xmlSchemaPCustomErr(ctxt,
10981 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10982 NULL, typeDecl, typeDecl->node,
10983 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000010984 return;
10985 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010986 if (typeDecl->base != NULL) {
10987 base =
10988 xmlSchemaGetType(ctxt->schema, typeDecl->base,
10989 typeDecl->baseNs);
10990 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010991 xmlSchemaPResCompAttrErr(ctxt,
10992 XML_SCHEMAP_SRC_RESOLVE,
10993 NULL, typeDecl, typeDecl->node,
10994 "base", typeDecl->base, typeDecl->baseNs,
10995 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010996 } else if (base->contentType ==
10997 XML_SCHEMA_CONTENT_UNKNOWN) {
10998 typeDecl->recurse = 1;
10999 xmlSchemaTypeFixup(base, ctxt, NULL);
11000 typeDecl->recurse = 0;
11001 }
11002 /*
11003 * The type definition ·resolved· to by the ·actual
11004 * value· of the base [attribute]
11005 */
11006 ctxt->ctxtType->baseType = base;
11007 /*
11008 * TODO: This one is still needed for computation of
11009 * the content model by xmlSchemaBuildAContentModel.
11010 * Try to get rid of it.
11011 */
11012 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011013 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011014 if ((typeDecl->subtypes != NULL) &&
11015 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
11016 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
11017
11018 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
11019 if (typeDecl->subtypes == NULL)
11020 /* 1.1.1 */
11021 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11022 else if ((typeDecl->subtypes->subtypes == NULL) &&
11023 ((typeDecl->subtypes->type ==
11024 XML_SCHEMA_TYPE_ALL)
11025 || (typeDecl->subtypes->type ==
11026 XML_SCHEMA_TYPE_SEQUENCE)))
11027 /* 1.1.2 */
11028 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11029 else if ((typeDecl->subtypes->type ==
11030 XML_SCHEMA_TYPE_CHOICE)
11031 && (typeDecl->subtypes->subtypes == NULL))
11032 /* 1.1.3 */
11033 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11034 if (base != NULL) {
11035 /* It will be reported later, if the base is missing. */
11036 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
11037 /* 2.1 */
11038 typeDecl->contentType = base->contentType;
11039 } else if (base->contentType ==
11040 XML_SCHEMA_CONTENT_EMPTY) {
11041 /* 2.2 imbitable ! */
11042 typeDecl->contentType =
11043 XML_SCHEMA_CONTENT_ELEMENTS;
11044 } else {
11045 /* 2.3 imbitable pareil ! */
11046 typeDecl->contentType =
11047 XML_SCHEMA_CONTENT_ELEMENTS;
11048 }
11049 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011050 break;
11051 }
11052 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011053 ctxtType = ctxt->ctxtType;
11054 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011055 if ((typeDecl->subtypes == NULL) ||
11056 ((typeDecl->subtypes->type !=
11057 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
11058 (typeDecl->subtypes->type !=
11059 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
11060 /*
11061 * This case is understood as shorthand for complex
11062 * content restricting the ur-type definition, and
11063 * the details of the mappings should be modified as
11064 * necessary.
11065 */
11066 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11067 typeDecl->flags |=
11068 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11069 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011070 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011071 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011072 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11073 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011074 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011075 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011076 if ((typeDecl->subtypes != NULL) &&
11077 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011078 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011079 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011080 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011081 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011082 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011083 typeDecl->contentType =
11084 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011085 } else {
11086 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011087 typeDecl->contentType =
11088 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011089 }
11090 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011091 }
11092 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011093 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011094 break;
11095 }
11096 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
11097 if (typeDecl->subtypes == NULL) {
11098 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000011099 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
11100 typeDecl->contentType =
11101 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011102 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000011103 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011104 typeDecl->contentType =
11105 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000011106 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011107 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
11108 NULL);
11109 if (typeDecl->subtypes != NULL)
11110 typeDecl->contentType =
11111 typeDecl->subtypes->contentType;
11112 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011113 /*
11114 * Removed due to implementation of the build of attribute uses.
11115 */
11116 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011117 if (typeDecl->attributes == NULL)
11118 typeDecl->attributes =
11119 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011120 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011121 }
11122 break;
11123 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011124 case XML_SCHEMA_TYPE_SIMPLE:
11125 /*
11126 * Simple Type Definition Schema Component
11127 *
11128 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011129 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011130 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11131 if (typeDecl->subtypes->contentType ==
11132 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011133 ctxt->ctxtType = typeDecl;
11134 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011135 }
11136 /* Fixup base type */
11137 if ((typeDecl->baseType != NULL) &&
11138 (typeDecl->baseType->contentType ==
11139 XML_SCHEMA_CONTENT_UNKNOWN)) {
11140 /* OPTIMIZE: Actually this one will never by hit, since
11141 * the base type is already type-fixed in <restriction>.
11142 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011143 ctxt->ctxtType = typeDecl;
11144 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011145 }
11146 /* Base type:
11147 * 2 If the <list> or <union> alternative is chosen,
11148 * then the ·simple ur-type definition·.
11149 */
11150 if (typeDecl->subtypes->type ==
11151 XML_SCHEMA_TYPE_LIST) {
11152 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11153 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11154 } else if (typeDecl->subtypes->type ==
11155 XML_SCHEMA_TYPE_UNION) {
11156 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11157 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11158 } else if (typeDecl->subtypes->type ==
11159 XML_SCHEMA_TYPE_RESTRICTION) {
11160 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
11161
11162 /*
11163 * Variety
11164 * If the <restriction> alternative is chosen, then the
11165 * {variety} of the {base type definition}.
11166 */
11167 if (typeDecl->baseType != NULL) {
11168 if (typeDecl->baseType->flags &
11169 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
11170 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
11171 else if (typeDecl->baseType->flags &
11172 XML_SCHEMAS_TYPE_VARIETY_LIST)
11173 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11174 else if (typeDecl->baseType->flags &
11175 XML_SCHEMAS_TYPE_VARIETY_UNION)
11176 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11177 /*
11178 * Schema Component Constraint: Simple Type Restriction
11179 * (Facets)
11180 * NOTE: Satisfaction of 1 and 2 arise from the fixup
11181 * applied beforehand.
11182 *
11183 * 3 The {facets} of R are the union of S and the {facets}
11184 * of B, eliminating duplicates. To eliminate duplicates,
11185 * when a facet of the same kind occurs in both S and the
11186 * {facets} of B, the one in the {facets} of B is not
11187 * included, with the exception of enumeration and pattern
11188 * facets, for which multiple occurrences with distinct values
11189 * are allowed.
11190 */
11191 if (typeDecl->baseType->facetSet != NULL) {
11192 last = typeDecl->facetSet;
11193 if (last != NULL)
11194 while (last->next != NULL)
11195 last = last->next;
11196 cur = typeDecl->baseType->facetSet;
11197 for (; cur != NULL; cur = cur->next) {
11198 /*
11199 * Base patterns won't be add here:
11200 * they are ORed in a type and
11201 * ANDed in derived types. This will
11202 * happed at validation level by
11203 * walking the base axis of the type.
11204 */
11205 if (cur->facet->type ==
11206 XML_SCHEMA_FACET_PATTERN)
11207 continue;
11208 facet = NULL;
11209 if ((typeDecl->facetSet != NULL) &&
11210 (cur->facet->type !=
11211 XML_SCHEMA_FACET_PATTERN) &&
11212 (cur->facet->type !=
11213 XML_SCHEMA_FACET_ENUMERATION)) {
11214 facet = typeDecl->facetSet;
11215 do {
11216 if (cur->facet->type ==
11217 facet->facet->type)
11218 break;
11219 facet = facet->next;
11220 } while (facet != NULL);
11221 }
11222 if (facet == NULL) {
11223 facet = (xmlSchemaFacetLinkPtr)
11224 xmlMalloc(sizeof(xmlSchemaFacetLink));
11225 if (facet == NULL) {
11226 xmlSchemaPErrMemory(ctxt,
11227 "fixing simpleType", NULL);
11228 return;
11229 }
11230 facet->facet = cur->facet;
11231 facet->next = NULL;
11232 if (last == NULL)
11233 typeDecl->facetSet = facet;
11234 else
11235 last->next = facet;
11236 last = facet;
11237 }
11238 }
11239 }
11240 }
11241 }
11242 /*
11243 * Check constraints.
11244 */
11245 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011246 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011247 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 case XML_SCHEMA_TYPE_SEQUENCE:
11249 case XML_SCHEMA_TYPE_GROUP:
11250 case XML_SCHEMA_TYPE_ALL:
11251 case XML_SCHEMA_TYPE_CHOICE:
11252 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11253 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011254 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +000011255 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011256 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11257 break;
11258 case XML_SCHEMA_TYPE_UNION:
11259 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
11260 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11261 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011262 case XML_SCHEMA_TYPE_BASIC:
11263 case XML_SCHEMA_TYPE_ANY:
11264 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011265 case XML_SCHEMA_TYPE_UR:
11266 case XML_SCHEMA_TYPE_ELEMENT:
11267 case XML_SCHEMA_TYPE_ATTRIBUTE:
11268 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000011269 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 case XML_SCHEMA_FACET_MININCLUSIVE:
11272 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11273 case XML_SCHEMA_FACET_MAXINCLUSIVE:
11274 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11275 case XML_SCHEMA_FACET_TOTALDIGITS:
11276 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11277 case XML_SCHEMA_FACET_PATTERN:
11278 case XML_SCHEMA_FACET_ENUMERATION:
11279 case XML_SCHEMA_FACET_WHITESPACE:
11280 case XML_SCHEMA_FACET_LENGTH:
11281 case XML_SCHEMA_FACET_MAXLENGTH:
11282 case XML_SCHEMA_FACET_MINLENGTH:
11283 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011284 if (typeDecl->subtypes != NULL)
11285 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 break;
11287 }
11288 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011289#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011290 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011291 xmlGenericError(xmlGenericErrorContext,
11292 "Type of %s : %s:%d :", name,
11293 typeDecl->node->doc->URL,
11294 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011295 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011297 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011298 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 case XML_SCHEMA_CONTENT_SIMPLE:
11300 xmlGenericError(xmlGenericErrorContext, "simple\n");
11301 break;
11302 case XML_SCHEMA_CONTENT_ELEMENTS:
11303 xmlGenericError(xmlGenericErrorContext, "elements\n");
11304 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011305 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
11307 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011308 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 xmlGenericError(xmlGenericErrorContext, "empty\n");
11310 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011311 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 xmlGenericError(xmlGenericErrorContext, "mixed\n");
11313 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011314 /* Removed, since not used. */
11315 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000011316 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011317 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
11318 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011319 */
Daniel Veillard8651f532002-04-17 09:06:27 +000011320 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011321 xmlGenericError(xmlGenericErrorContext, "basic\n");
11322 break;
11323 default:
11324 xmlGenericError(xmlGenericErrorContext,
11325 "not registered !!!\n");
11326 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011327 }
11328#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011329}
11330
11331/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011332 * xmlSchemaCheckFacet:
11333 * @facet: the facet
11334 * @typeDecl: the schema type definition
11335 * @ctxt: the schema parser context or NULL
11336 * @name: name of the type
11337 *
11338 * Checks the default values types, especially for facets
11339 *
11340 * Returns 0 if okay or -1 in cae of error
11341 */
11342int
11343xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011344 xmlSchemaTypePtr typeDecl,
11345 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011346{
11347 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
11348 int ret = 0;
11349
11350 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011351 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011352 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011353 }
11354 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011355 case XML_SCHEMA_FACET_MININCLUSIVE:
11356 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11357 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011358 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11359 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 /*
11361 * Okay we need to validate the value
11362 * at that point.
11363 */
11364 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011365 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011366
11367 /* 4.3.5.5 Constraints on enumeration Schema Components
11368 * Schema Component Constraint: enumeration valid restriction
11369 * It is an ·error· if any member of {value} is not in the
11370 * ·value space· of {base type definition}.
11371 *
11372 * minInclusive, maxInclusive, minExclusive, maxExclusive:
11373 * The value ·must· be in the
11374 * ·value space· of the ·base type·.
11375 */
11376 /*
11377 * This function is intended to deliver a compiled value
11378 * on the facet. In XML Schemas the type holding a facet,
11379 * cannot be a built-in type. Thus to ensure that other API
11380 * calls (relaxng) do work, if the given type is a built-in
11381 * type, we will assume that the given built-in type *is
11382 * already* the base type.
11383 */
11384 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
11385 base = typeDecl->baseType;
11386 if (base == NULL) {
11387 xmlSchemaPErr(ctxt, typeDecl->node,
11388 XML_SCHEMAS_ERR_INTERNAL,
11389 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011390 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011391 typeDecl->name, NULL);
11392 return (-1);
11393 }
11394 } else
11395 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011396 /*
11397 * TODO: Try to avoid creating a new context.
11398 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011399 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011400 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011401 xmlSchemaPErr(ctxt, typeDecl->node,
11402 XML_SCHEMAS_ERR_INTERNAL,
11403 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011404 "creating a new validation context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011405 NULL, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011406 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011407 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011408 vctxt->type = base;
11409 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011410 facet->val = vctxt->value;
11411 vctxt->value = NULL;
11412 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011413 /* error code */
11414 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011415 xmlSchemaPErrExt(ctxt, facet->node,
11416 XML_SCHEMAP_INVALID_FACET,
11417 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 "Type definition '%s': The value '%s' of the "
11419 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011420 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011421 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011422 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011423 }
11424 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011425 } else if (ret < 0) {
11426 xmlSchemaPErrExt(ctxt, facet->node,
11427 XML_SCHEMAS_ERR_INTERNAL,
11428 NULL, NULL, NULL,
11429 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011430 "failed to validate the value '%s' name of the "
11431 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000011432 facet->value,
11433 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
11434 base->name, NULL, NULL);
11435 ret = -1;
11436 }
11437 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011438 break;
11439 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011440 case XML_SCHEMA_FACET_PATTERN:
11441 facet->regexp = xmlRegexpCompile(facet->value);
11442 if (facet->regexp == NULL) {
11443 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011444 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011445 "Type definition '%s': The value '%s' of the "
11446 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011447 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011448 ret = -1;
11449 }
11450 break;
11451 case XML_SCHEMA_FACET_TOTALDIGITS:
11452 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11453 case XML_SCHEMA_FACET_LENGTH:
11454 case XML_SCHEMA_FACET_MAXLENGTH:
11455 case XML_SCHEMA_FACET_MINLENGTH:{
11456 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011457
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011458 tmp =
11459 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
11460 facet->value,
11461 &facet->val);
11462 if (tmp != 0) {
11463 /* error code */
11464 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011465 xmlSchemaPErrExt(ctxt, facet->node,
11466 XML_SCHEMAP_INVALID_FACET_VALUE,
11467 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011468 "Type definition '%s': The value '%s' of the "
11469 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011470 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011471 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000011472 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011473 }
11474 ret = -1;
11475 }
11476 break;
11477 }
11478 case XML_SCHEMA_FACET_WHITESPACE:{
11479 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
11480 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
11481 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
11482 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
11483 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
11484 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
11485 } else {
11486 if (ctxt != NULL) {
11487 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011488 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011489 "Type definition '%s': The value '%s' of the "
11490 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011491 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011492 }
11493 ret = -1;
11494 }
11495 }
11496 default:
11497 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011499 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011500}
11501
11502/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011503 * xmlSchemaCheckDefaults:
11504 * @typeDecl: the schema type definition
11505 * @ctxt: the schema parser context
11506 *
11507 * Checks the default values types, especially for facets
11508 */
11509static void
11510xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011511 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011512{
Daniel Veillard4255d502002-04-16 15:50:10 +000011513 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011514 name = typeDecl->name;
11515 /*
11516 * NOTE: It is intended to use the facets list, instead
11517 * of facetSet.
11518 */
11519 if (typeDecl->facets != NULL) {
11520 xmlSchemaFacetPtr facet = typeDecl->facets;
11521
11522 while (facet != NULL) {
11523 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
11524 facet = facet->next;
11525 }
11526 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011527}
11528
11529/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000011530 * xmlSchemaAttrGrpFixup:
11531 * @attrgrpDecl: the schema attribute definition
11532 * @ctxt: the schema parser context
11533 * @name: the attribute name
11534 *
11535 * Fixes finish doing the computations on the attributes definitions
11536 */
11537static void
Daniel Veillard3646d642004-06-02 19:19:14 +000011538xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011539 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000011540{
11541 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011542 name = attrgrp->name;
11543 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011544 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000011545 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011546 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000011547
Daniel Veillardc0826a72004-08-10 14:17:33 +000011548 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
11549 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011550 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011551 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011552 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011553 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
11554 "ref", attrgrp->ref, attrgrp->refNs,
11555 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011556 return;
11557 }
11558 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011559 attrgrp->attributes = ref->attributes;
11560 attrgrp->attributeWildcard = ref->attributeWildcard;
11561 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000011562}
11563
11564/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011565 * xmlSchemaAttrFixup:
11566 * @attrDecl: the schema attribute definition
11567 * @ctxt: the schema parser context
11568 * @name: the attribute name
11569 *
11570 * Fixes finish doing the computations on the attributes definitions
11571 */
11572static void
11573xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011574 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011575{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011576 /*
11577 * TODO: If including this is done twice (!) for every attribute.
11578 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011579 /*
11580 * The simple type definition corresponding to the <simpleType> element
11581 * information item in the [children], if present, otherwise the simple
11582 * type definition ·resolved· to by the ·actual value· of the type
11583 * [attribute], if present, otherwise the ·simple ur-type definition·.
11584 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011585 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
11586 return;
11587 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000011588 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011589 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000011590 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011591 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011592 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011593 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011594
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
11596 attrDecl->typeNs);
11597 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011598 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011599 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011600 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11601 "type", attrDecl->typeName, attrDecl->typeNs,
11602 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011603 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011604 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011605 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011606 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000011607
Daniel Veillardc0826a72004-08-10 14:17:33 +000011608 /*
11609 * TODO: Evaluate, what errors could occur if the declaration is not
11610 * found. It might be possible that the "typefixup" might crash if
11611 * no ref declaration was found.
11612 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011613 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011614 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011615 xmlSchemaPResCompAttrErr(ctxt,
11616 XML_SCHEMAP_SRC_RESOLVE,
11617 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
11618 "ref", attrDecl->ref, attrDecl->refNs,
11619 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011620 return;
11621 }
11622 xmlSchemaAttrFixup(ref, ctxt, NULL);
11623 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011624 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011625 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000011626 }
11627}
11628
11629/**
11630 * xmlSchemaParse:
11631 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011632 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011633 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000011634 * XML Shema struture which can be used to validate instances.
11635 * *WARNING* this interface is highly subject to change
11636 *
11637 * Returns the internal XML Schema structure built from the resource or
11638 * NULL in case of error
11639 */
11640xmlSchemaPtr
11641xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
11642{
11643 xmlSchemaPtr ret = NULL;
11644 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011645 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011646 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011647 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011648
11649 xmlSchemaInitTypes();
11650
Daniel Veillard6045c902002-10-09 21:13:59 +000011651 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000011652 return (NULL);
11653
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011654 nberrors = ctxt->nberrors;
11655 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011656 ctxt->counter = 0;
11657 ctxt->container = NULL;
11658
11659 /*
11660 * First step is to parse the input document into an DOM/Infoset
11661 */
Daniel Veillard6045c902002-10-09 21:13:59 +000011662 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011663 doc = xmlReadFile((const char *) ctxt->URL, NULL,
11664 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011665 if (doc == NULL) {
11666 xmlSchemaPErr(ctxt, NULL,
11667 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011668 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011669 ctxt->URL, NULL);
11670 return (NULL);
11671 }
Daniel Veillard6045c902002-10-09 21:13:59 +000011672 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011673 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
11674 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011675 if (doc == NULL) {
11676 xmlSchemaPErr(ctxt, NULL,
11677 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011678 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011679 NULL, NULL);
11680 return (NULL);
11681 }
11682 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000011683 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000011684 } else if (ctxt->doc != NULL) {
11685 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011686 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000011687 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011688 xmlSchemaPErr(ctxt, NULL,
11689 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011690 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011691 NULL, NULL);
11692 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011693 }
11694
11695 /*
11696 * Then extract the root and Schema parse it
11697 */
11698 root = xmlDocGetRootElement(doc);
11699 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011700 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11701 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011702 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000011703 if (!preserve) {
11704 xmlFreeDoc(doc);
11705 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011706 return (NULL);
11707 }
11708
11709 /*
11710 * Remove all the blank text nodes
11711 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011712 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000011713
11714 /*
11715 * Then do the parsing for good
11716 */
11717 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000011718 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000011719 if (!preserve) {
11720 xmlFreeDoc(doc);
11721 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011722 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000011723 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011724 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011725 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000011726 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011727 ctxt->ctxtType = NULL;
11728 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011729 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000011730 * Then fixup all attributes declarations
11731 */
11732 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
11733
11734 /*
11735 * Then fixup all attributes group declarations
11736 */
11737 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
11738 ctxt);
11739
11740 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000011741 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000011742 */
11743 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
11744
11745 /*
11746 * Then fix references of element declaration; apply constraints.
11747 */
11748 xmlHashScanFull(ret->elemDecl,
11749 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011750
11751 /*
11752 * Then build the content model for all elements
11753 */
11754 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011755 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011756
11757 /*
11758 * Then check the defaults part of the type like facets values
11759 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011760 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
11761 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011762
Daniel Veillardc0826a72004-08-10 14:17:33 +000011763
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011764 if (ctxt->nberrors != 0) {
11765 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011766 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011767 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011768 return (ret);
11769}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011770
Daniel Veillard4255d502002-04-16 15:50:10 +000011771/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000011772 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000011773 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000011774 * @err: the error callback
11775 * @warn: the warning callback
11776 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000011777 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000011778 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000011779 */
11780void
11781xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011782 xmlSchemaValidityErrorFunc err,
11783 xmlSchemaValidityWarningFunc warn, void *ctx)
11784{
Daniel Veillard4255d502002-04-16 15:50:10 +000011785 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011786 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011787 ctxt->error = err;
11788 ctxt->warning = warn;
11789 ctxt->userData = ctx;
11790}
11791
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011792/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000011793 * xmlSchemaGetParserErrors:
11794 * @ctxt: a XMl-Schema parser context
11795 * @err: the error callback result
11796 * @warn: the warning callback result
11797 * @ctx: contextual data for the callbacks result
11798 *
11799 * Get the callback information used to handle errors for a parser context
11800 *
11801 * Returns -1 in case of failure, 0 otherwise
11802 */
11803int
11804xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
11805 xmlSchemaValidityErrorFunc * err,
11806 xmlSchemaValidityWarningFunc * warn, void **ctx)
11807{
11808 if (ctxt == NULL)
11809 return(-1);
11810 if (err != NULL)
11811 *err = ctxt->error;
11812 if (warn != NULL)
11813 *warn = ctxt->warning;
11814 if (ctx != NULL)
11815 *ctx = ctxt->userData;
11816 return(0);
11817}
11818
11819/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011820 * xmlSchemaFacetTypeToString:
11821 * @type: the facet type
11822 *
11823 * Convert the xmlSchemaTypeType to a char string.
11824 *
11825 * Returns the char string representation of the facet type if the
11826 * type is a facet and an "Internal Error" string otherwise.
11827 */
11828static const char *
11829xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
11830{
11831 switch (type) {
11832 case XML_SCHEMA_FACET_PATTERN:
11833 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011834 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011835 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011836 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011837 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011838 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011839 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011840 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011841 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011842 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011843 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011844 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011845 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011846 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011847 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011848 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011849 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011850 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011851 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011852 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011853 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011854 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011855 return ("fractionDigits");
11856 default:
11857 break;
11858 }
11859 return ("Internal Error");
11860}
11861
Daniel Veillardc0826a72004-08-10 14:17:33 +000011862static xmlChar *
11863xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
11864 const xmlChar *cur = value;
11865 xmlChar *ret = NULL, *mcur;
11866
11867 if (value == NULL)
11868 return(NULL);
11869
11870 while ((*cur != 0) &&
11871 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
11872 cur++;
11873 }
11874 if (*cur == 0)
11875 return (NULL);
11876 ret = xmlStrdup(value);
11877 /* TODO FIXME: I guess gcc will bark at this. */
11878 mcur = (xmlChar *) (ret + (cur - value));
11879 do {
11880 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
11881 *mcur = ' ';
11882 mcur++;
11883 } while (*mcur != 0);
11884 return(ret);
11885}
11886
11887static int
11888xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
11889{
11890 xmlSchemaTypePtr anc;
11891
11892 /*
11893 * The normalization type can be changed only for types which are derived
11894 * from xsd:string.
11895 */
11896 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11897 if ((type->builtInType == XML_SCHEMAS_STRING) &&
11898 (type->builtInType == XML_SCHEMAS_NORMSTRING))
11899
11900 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11901 else {
11902 /*
11903 * For all ·atomic· datatypes other than string (and types ·derived·
11904 * by ·restriction· from it) the value of whiteSpace is fixed to
11905 * collapse
11906 */
11907 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11908 }
11909 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11910 /*
11911 * For list types the facet "whiteSpace" is fixed to "collapse".
11912 */
11913 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11914 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11915 return (-1);
11916 } else if (type->facetSet != NULL) {
11917 xmlSchemaTypePtr anyST;
11918 xmlSchemaFacetLinkPtr lin;
11919
11920 /*
11921 * Atomic types.
11922 */
11923 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11924 anc = type->baseType;
11925 do {
11926 /*
11927 * For all ·atomic· datatypes other than string (and types ·derived·
11928 * by ·restriction· from it) the value of whiteSpace is fixed to
11929 * collapse
11930 */
11931 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
11932 (anc->builtInType == XML_SCHEMAS_STRING)) {
11933
11934 lin = type->facetSet;
11935 do {
11936 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
11937 if (lin->facet->whitespace ==
11938 XML_SCHEMAS_FACET_COLLAPSE) {
11939 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11940 } else if (lin->facet->whitespace ==
11941 XML_SCHEMAS_FACET_REPLACE) {
11942 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
11943 } else
11944 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11945 break;
11946 }
11947 lin = lin->next;
11948 } while (lin != NULL);
11949 break;
11950 }
11951 anc = anc->baseType;
11952 } while (anc != anyST);
11953 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11954 }
11955 return (-1);
11956}
11957
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011958/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000011959 * xmlSchemaValidateFacetsInternal:
11960 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000011961 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000011962 * @facets: the list of facets to check
11963 * @value: the lexical repr of the value to validate
11964 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000011965 * @fireErrors: if 0, only internal errors will be fired;
11966 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000011967 *
11968 * Check a value against all facet conditions
11969 *
11970 * Returns 0 if the element is schemas valid, a positive error code
11971 * number otherwise and -1 in case of internal or API error.
11972 */
11973static int
11974xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011975 xmlSchemaTypePtr type,
11976 const xmlChar * value,
11977 unsigned long length,
11978 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011979{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011980 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011981 xmlSchemaTypePtr biType; /* The build-in type. */
11982 xmlSchemaTypePtr tmpType;
11983 xmlSchemaFacetLinkPtr facetLink;
11984 int retFacet, hasFacet;
11985 xmlSchemaFacetPtr facet;
11986 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011987
Daniel Veillardc0826a72004-08-10 14:17:33 +000011988#ifdef DEBUG_UNION_VALIDATION
11989 printf("Facets of type: '%s'\n", (const char *) type->name);
11990 printf(" fireErrors: %d\n", fireErrors);
11991#endif
11992
11993 /*
11994 * NOTE: Do not jump away, if the facetSet of the given type is
11995 * empty: until now, "pattern" facets of the *base types* need to
11996 * be checked as well.
11997 */
11998 biType = type->baseType;
11999 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12000 biType = biType->baseType;
12001 if (biType == NULL) {
12002 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12003 "Internal error: xmlSchemaValidateFacetsInternal, "
12004 "the base type axis of the given type '%s' does not resolve to "
12005 "a built-in type.\n",
12006 type->name, NULL);
12007 return (-1);
12008 }
12009
12010 if (type->facetSet != NULL) {
12011 facetLink = type->facetSet;
12012 while (facetLink != NULL) {
12013 facet = facetLink->facet;
12014 /*
12015 * Skip the pattern "whiteSpace": it is used to
12016 * format the character content beforehand.
12017 */
12018 switch (facet->type) {
12019 case XML_SCHEMA_FACET_WHITESPACE:
12020 case XML_SCHEMA_FACET_PATTERN:
12021 case XML_SCHEMA_FACET_ENUMERATION:
12022 break;
12023 case XML_SCHEMA_FACET_LENGTH:
12024 case XML_SCHEMA_FACET_MINLENGTH:
12025 case XML_SCHEMA_FACET_MAXLENGTH:
12026 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12027 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12028 value, length, 0);
12029 len = length;
12030 } else
12031 ret = xmlSchemaValidateLengthFacet(biType, facet,
12032 value, ctxt->value, &len);
12033 break;
12034 default:
12035 ret = xmlSchemaValidateFacet(biType, facet, value,
12036 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012037 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012038 if (ret < 0) {
12039 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12040 "Internal error: xmlSchemaValidateFacetsInternal, "
12041 "validating facet of type '%s'.\n",
12042 type->name, NULL);
12043 break;
12044 } else if ((ret > 0) && (fireErrors)) {
12045 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, len,
12046 type, facet, NULL, NULL, NULL, NULL);
12047 }
12048
12049 facetLink = facetLink->next;
12050 }
12051 if (ret >= 0) {
12052 /*
12053 * Process enumerations.
12054 */
12055 retFacet = 0;
12056 facetLink = type->facetSet;
12057 while (facetLink != NULL) {
12058 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12059 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12060 value, ctxt->value);
12061 if (retFacet <= 0)
12062 break;
12063 }
12064 facetLink = facetLink->next;
12065 }
12066 if (retFacet > 0) {
12067 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12068 if (fireErrors)
12069 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur,
12070 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12071 } else if (retFacet < 0) {
12072 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12073 "Internal error: xmlSchemaValidateFacetsInternal, "
12074 "validating facet of type '%s'.\n",
12075 BAD_CAST "enumeration", NULL);
12076 ret = -1;
12077 }
12078 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012079 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012080 if (ret >= 0) {
12081 /*
12082 * Process patters. Pattern facets are ORed at type level
12083 * and ANDed if derived. Walk the base type axis.
12084 */
12085 hasFacet = 0;
12086 tmpType = type;
12087 facet = NULL;
12088 do {
12089 retFacet = 0;
12090 for (facetLink = tmpType->facetSet; facetLink != NULL;
12091 facetLink = facetLink->next) {
12092 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
12093 continue;
12094 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12095 value, ctxt->value);
12096 if (retFacet <= 0)
12097 break;
12098 else
12099 /* Save the last non-validating facet. */
12100 facet = facetLink->facet;
12101 }
12102 if (retFacet != 0)
12103 break;
12104 tmpType = tmpType->baseType;
12105 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
12106 if (retFacet < 0) {
12107 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12108 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12109 "validating 'pattern' facets of type '%s'.\n",
12110 tmpType->name, NULL);
12111 ret = -1;
12112 } else if (retFacet > 0) {
12113 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
12114 if (fireErrors) {
12115 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, 0, type, facet,
12116 NULL, NULL, NULL, NULL);
12117 }
12118 }
12119 }
12120
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012121 return (ret);
12122}
12123
Daniel Veillard4255d502002-04-16 15:50:10 +000012124/************************************************************************
12125 * *
12126 * Simple type validation *
12127 * *
12128 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000012129
Daniel Veillard4255d502002-04-16 15:50:10 +000012130
12131/************************************************************************
12132 * *
12133 * DOM Validation code *
12134 * *
12135 ************************************************************************/
12136
12137static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012138 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012139static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012140 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000012141 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012142static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012143 xmlNodePtr elem,
12144 xmlSchemaElementPtr elemDecl,
12145 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000012146
Daniel Veillard3646d642004-06-02 19:19:14 +000012147
12148/**
12149 * xmlSchemaFreeAttrStates:
12150 * @state: a list of attribute states
12151 *
12152 * Free the given list of attribute states
12153 *
12154 */
12155static void
12156xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
12157{
12158 xmlSchemaAttrStatePtr tmp;
12159 while (state != NULL) {
12160 tmp = state;
12161 state = state->next;
12162 xmlFree(tmp);
12163 }
12164}
12165
Daniel Veillard4255d502002-04-16 15:50:10 +000012166/**
12167 * xmlSchemaRegisterAttributes:
12168 * @ctxt: a schema validation context
12169 * @attrs: a list of attributes
12170 *
12171 * Register the list of attributes as the set to be validated on that element
12172 *
12173 * Returns -1 in case of error, 0 otherwise
12174 */
12175static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012176xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
12177{
Daniel Veillard3646d642004-06-02 19:19:14 +000012178 xmlSchemaAttrStatePtr tmp;
12179
12180 ctxt->attr = NULL;
12181 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012182 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012183 if ((attrs->ns != NULL) &&
12184 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
12185 attrs = attrs->next;
12186 continue;
12187 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012188 tmp = (xmlSchemaAttrStatePtr)
12189 xmlMalloc(sizeof(xmlSchemaAttrState));
12190 if (tmp == NULL) {
12191 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
12192 return (-1);
12193 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012194 tmp->attr = attrs;
12195 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
12196 tmp->next = NULL;
12197 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012198 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012199 else
12200 ctxt->attrTop->next = tmp;
12201 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012202 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012203 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012204 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000012205}
12206
12207/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012208 * xmlSchemaValidateCheckNodeList
12209 * @nodelist: the list of nodes
12210 *
12211 * Check the node list is only made of text nodes and entities pointing
12212 * to text nodes
12213 *
12214 * Returns 1 if true, 0 if false and -1 in case of error
12215 */
12216static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012217xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
12218{
Daniel Veillard4255d502002-04-16 15:50:10 +000012219 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012220 if (nodelist->type == XML_ENTITY_REF_NODE) {
12221 TODO /* implement recursion in the entity content */
12222 }
12223 if ((nodelist->type != XML_TEXT_NODE) &&
12224 (nodelist->type != XML_COMMENT_NODE) &&
12225 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000012226 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012227 return (0);
12228 }
12229 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012230 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012231 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012232}
12233
12234/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012235 * xmlSchemaValidateCallback:
12236 * @ctxt: a schema validation context
12237 * @name: the name of the element detected (might be NULL)
12238 * @type: the type
12239 *
12240 * A transition has been made in the automata associated to an element
12241 * content model
12242 */
12243static void
12244xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012245 const xmlChar * name ATTRIBUTE_UNUSED,
12246 xmlSchemaTypePtr type, xmlNodePtr node)
12247{
Daniel Veillard4255d502002-04-16 15:50:10 +000012248 xmlSchemaTypePtr oldtype = ctxt->type;
12249 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012250
Daniel Veillard4255d502002-04-16 15:50:10 +000012251#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000012252 xmlGenericError(xmlGenericErrorContext,
12253 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012254 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012255#endif
12256 ctxt->type = type;
12257 ctxt->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012258 xmlSchemaValidateContent(ctxt, node);
Daniel Veillard4255d502002-04-16 15:50:10 +000012259 ctxt->type = oldtype;
12260 ctxt->node = oldnode;
12261}
12262
Daniel Veillard01fa6152004-06-29 17:04:39 +000012263#if 0 /* Not used any more */
Daniel Veillard4255d502002-04-16 15:50:10 +000012264/**
12265 * xmlSchemaValidateSimpleType:
12266 * @ctxt: a schema validation context
12267 * @node: the top node.
12268 *
12269 * Validate the content of an simple type.
12270 *
12271 * Returns 0 if the element is schemas valid, a positive error code
12272 * number otherwise and -1 in case of internal or API error.
12273 */
12274static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012275xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12276{
Daniel Veillard4255d502002-04-16 15:50:10 +000012277 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +000012278 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +000012279 xmlAttrPtr attr;
12280 int ret;
William M. Bracke7091952004-05-11 15:09:58 +000012281 xmlChar *value;
12282
Daniel Veillard4255d502002-04-16 15:50:10 +000012283
12284 child = ctxt->node;
12285 type = ctxt->type;
12286
12287 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000012288 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12289 "Internal error: xmlSchemaValidateSimpleType %s\n",
12290 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012291 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012292 }
12293 /*
12294 * Only text and text based entities references shall be found there
12295 */
12296 ret = xmlSchemaValidateCheckNodeList(child);
12297 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000012298 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12299 "Internal error: xmlSchemaValidateSimpleType %s content\n",
12300 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012301 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012302 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000012303 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
12304 "Element %s content is not a simple type\n",
12305 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012306 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012307 }
12308 /*
12309 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +000012310 */
12311
Daniel Veillard4255d502002-04-16 15:50:10 +000012312 attr = node->properties;
12313 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012314 if ((attr->ns == NULL) ||
12315 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
12316 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
12317 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
12318 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
12319 (!xmlStrEqual
12320 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +000012321 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
12322 "Element %s: attribute %s should not be present\n",
12323 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012324 return (ctxt->err);
12325 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012326 }
William M. Bracke7091952004-05-11 15:09:58 +000012327 /* TODO:
12328 * If {variety} is ·atomic· then the {variety} of {base type definition}
12329 * must be ·atomic·.
12330 * If {variety} is ·list· then the {variety} of {item type definition}
12331 * must be either ·atomic· or ·union·.
12332 * If {variety} is ·union· then {member type definitions} must be a list
12333 * of datatype definitions.
12334 */
12335 if (type->subtypes == NULL) {
12336 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12337 "Internal error: xmlSchemaValidateSimpleType; "
12338 "simple type %s does not define a variety\n",
12339 node->name, NULL);
12340 return (ctxt->err);
12341 }
12342 /* Varieties: Restriction or List or Union. */
12343 variety = type->subtypes;
12344 ctxt->type = variety;
12345 value = xmlNodeGetContent(child);
12346 switch (variety->type) {
12347 case XML_SCHEMA_TYPE_RESTRICTION:{
William M. Bracke7091952004-05-11 15:09:58 +000012348 base = variety->baseType;
12349 if (base != NULL) {
12350 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
12351 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012352 TODO}
William M. Bracke7091952004-05-11 15:09:58 +000012353 break;
12354 }
12355 case XML_SCHEMA_TYPE_LIST:
12356 case XML_SCHEMA_TYPE_UNION: {
12357 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
12358 break;
12359 }
12360 default:{
12361 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12362 "Internal error: xmlSchemaValidateSimpleType; "
12363 "simple type %s defines unknown content: %s\n",
12364 variety->name, NULL);
12365 ret = ctxt->err;
12366 }
12367 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 if ((ret == 0) && (variety->facetSet != NULL)) {
12369 ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
12370 }
William M. Bracke7091952004-05-11 15:09:58 +000012371 if (value != NULL)
12372 xmlFree(value);
12373
12374 /* This was removed, since a simple content is not a content of a
12375 * simple type, but of a complex type.
12376 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
12377 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012378 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012379 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000012380}
Daniel Veillard01fa6152004-06-29 17:04:39 +000012381#endif
12382
Daniel Veillardc0826a72004-08-10 14:17:33 +000012383
12384
Daniel Veillard01fa6152004-06-29 17:04:39 +000012385/**
12386 * xmlSchemaValidateSimpleTypeValue:
12387 * @ctxt: a schema validation context
12388 * @value: the value to be validated
12389 * @fireErrors: shall errors be reported?
12390 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000012391 * @normalize: shall the value be normalized?
Daniel Veillard01fa6152004-06-29 17:04:39 +000012392 *
12393 * Validates a value by the given type (user derived or built-in).
12394 *
12395 * Returns 0 if the value is valid, a positive error code
12396 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 */
12398static int
12399xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
12400 const xmlChar *value,
12401 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012402 int applyFacets,
12403 int normalize)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012404{
12405 xmlSchemaTypePtr type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012406 int ret = 0;
12407 xmlChar *normValue = NULL;
12408 int wtsp;
12409
12410 type = ctxt->type;
12411 wtsp = ctxt->valueWS;
12412 /*
12413 * Normalize the value.
12414 */
12415 if (normalize &&
12416 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
12417 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
12418
12419 if ((norm != -1) && (norm > ctxt->valueWS)) {
12420 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12421 normValue = xmlSchemaCollapseString(value);
12422 else
12423 normValue = xmlSchemaWhiteSpaceReplace(value);
12424 ctxt->valueWS = norm;
12425 if (normValue != NULL)
12426 value = (const xmlChar *) normValue;
12427 }
12428 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012429 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
12430 xmlSchemaTypePtr base, anyType;
12431
12432 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12433
12434 base = type->baseType;
12435 while ((base != NULL) &&
12436 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
12437 (base->type != XML_SCHEMA_TYPE_BASIC) &&
12438 (base != anyType)) {
12439 base = base->baseType;
12440 }
12441 ctxt->type = base;
12442 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 0, 1);
12443 ctxt->type = type;
12444 if (ret < 0) {
12445 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12446 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12447 "validating complex type '%s'\n",
12448 type->name, NULL);
12449 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12450 /*
12451 * Check facets.
12452 */
12453 /*
12454 * This is somehow not nice, since if an error occurs
12455 * the reported type will be the complex type; the spec
12456 * wants a simple type to be created on the complex type
12457 * if it has a simple content. For now we have to live with
12458 * it.
12459 */
12460 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12461 value, 0, fireErrors);
12462 if (ret < 0) {
12463 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12464 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12465 "validating facets of complex type '%s'\n",
12466 type->name, NULL);
12467 } else if (ret > 0) {
12468 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
12469 /*
12470 Disabled, since the facet validation already reports errors.
12471 if (fireErrors)
12472 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12473 */
12474 }
12475 }
12476 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012477 xmlNodePtr child;
12478
12479 if (ctxt->value != NULL) {
12480 xmlSchemaFreeValue(ctxt->value);
12481 ctxt->value = NULL;
12482 }
12483 child = ctxt->node;
12484 while (child != NULL) {
12485 switch (child->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012486 case XML_TEXT_NODE:
12487 case XML_CDATA_SECTION_NODE:
12488 case XML_PI_NODE:
12489 case XML_COMMENT_NODE:
12490 case XML_XINCLUDE_START:
12491 case XML_XINCLUDE_END:
12492 break;
12493 case XML_ENTITY_REF_NODE:
12494 case XML_ENTITY_NODE:
12495 TODO break;
12496 case XML_ELEMENT_NODE: {
12497 xmlChar *strE = NULL;
12498
12499 xmlSchemaVErrExt(ctxt, ctxt->cur,
12500 XML_SCHEMAS_ERR_INVALIDELEM,
12501 "Element '%s': The child '%s' should "
12502 "not be present.\n",
12503 xmlSchemaFormatNsPrefixLocal(&strE,
12504 ctxt->cur->parent->ns, ctxt->cur->parent->name),
12505 child->name, NULL, NULL, NULL);
12506 FREE_AND_NULL(strE);
12507 return (ctxt->err);
12508 }
12509 case XML_ATTRIBUTE_NODE:
12510 case XML_DOCUMENT_NODE:
12511 case XML_DOCUMENT_TYPE_NODE:
12512 case XML_DOCUMENT_FRAG_NODE:
12513 case XML_NOTATION_NODE:
12514 case XML_HTML_DOCUMENT_NODE:
12515 case XML_DTD_NODE:
12516 case XML_ELEMENT_DECL:
12517 case XML_ATTRIBUTE_DECL:
12518 case XML_ENTITY_DECL:
12519 case XML_NAMESPACE_DECL:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012520#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardc0826a72004-08-10 14:17:33 +000012521 case XML_DOCB_DOCUMENT_NODE:
12522#endif
12523 {
12524 xmlChar *strE = NULL, *strA = NULL;
12525
12526 if (ctxt->cur->type == XML_ATTRIBUTE_NODE) {
12527 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
12528 "Element '%s', attribute '%s': The type of node is "
12529 "unexpected here.\n",
12530 xmlSchemaFormatNsPrefixLocal(&strE, ctxt->cur->parent->ns,
12531 ctxt->cur->parent->name),
12532 xmlSchemaFormatNsPrefixLocal(&strA, ctxt->cur->ns,
12533 ctxt->cur->name));
12534 } else {
12535 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
12536 "Element '%s': The type of node is unexpected here.\n",
12537 xmlSchemaFormatNsPrefixLocal(&strE, ctxt->cur->ns,
12538 ctxt->cur->name), NULL);
12539 }
12540 FREE_AND_NULL(strE);
12541 FREE_AND_NULL(strA);
12542 return (ctxt->err);
12543 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012544 }
12545 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012546
12547 }
12548 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), ctxt->cur);
12549 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012550 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
12551 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
12552 else
12553 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012554 if (fireErrors)
12555 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012556 } else if (ret < 0) {
12557 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12558 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012559 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 }
12561 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12562 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
12563 * a literal in the ·lexical space· of {base type definition}
12564 */
12565 ctxt->type = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012566 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0, 0);
12567 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012568 if (ret < 0) {
12569 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12570 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012571 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012572 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012573 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012575 if (fireErrors)
12576 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12577 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012578 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012579 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012580 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012581 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12582 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012583 if (ret < 0) {
12584 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12585 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012586 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012587 type->name, NULL);
12588 } else if (ret > 0) {
12589 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012590 /*
12591 Disabled, since the facet validation already reports errors.
12592 if (fireErrors)
12593 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12594 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012595 }
12596 }
12597 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12598
12599 xmlSchemaTypePtr tmpType;
12600 const xmlChar *cur, *end;
12601 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012602 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012603
12604 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
12605 * of white space separated tokens, each of which ·match·es a literal
12606 * in the ·lexical space· of {item type definition}
12607 */
12608
Daniel Veillardc0826a72004-08-10 14:17:33 +000012609 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012610 cur = value;
12611 do {
12612 while (IS_BLANK_CH(*cur))
12613 cur++;
12614 end = cur;
12615 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
12616 end++;
12617 if (end == cur)
12618 break;
12619 tmp = xmlStrndup(cur, end - cur);
12620 len++;
12621 ctxt->type = tmpType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1, 0);
12623 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012624 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012625 if (ret < 0) {
12626 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12627 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12628 "validating an item of list simple type '%s'\n",
12629 type->name, NULL);
12630 break;
12631 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012632 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012633 if (fireErrors)
12634 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012635 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012636 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012637 cur = end;
12638 } while (*cur != 0);
12639 /*
12640 * Check facets.
12641 */
12642 if (ret < 0) {
12643 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12644 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012645 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012646 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012647 } else if ((ret == 0) && (applyFacets)) {
12648 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12649 value, len, fireErrors);
12650 if (ret < 0) {
12651 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12652 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12653 "validating facets of list simple type '%s'\n",
12654 type->name, NULL);
12655 } else if (ret > 0) {
12656 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012657 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012658 Disabled, since the facet validation already reports errors.
12659 if (fireErrors)
12660 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012661 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012662 }
12663
Daniel Veillard01fa6152004-06-29 17:04:39 +000012664 }
12665 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12666 xmlSchemaTypeLinkPtr memberLink;
12667
12668 /*
12669 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
12670 * not apply directly; however, the normalization behavior of ·union·
12671 * types is controlled by the value of whiteSpace on that one of the
12672 * ·memberTypes· against which the ·union· is successfully validated.
12673 *
12674 * This means that the value is normalized by the first validating
12675 * member type, then the facets of the union type are applied. This
12676 * needs changing of the value!
12677 */
12678
12679 /*
12680 * 1.2.3 if {variety} is ·union· then the string must ·match· a
12681 * literal in the ·lexical space· of at least one member of
12682 * {member type definitions}
12683 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012684#ifdef DEBUG_UNION_VALIDATION
12685 printf("Union ST : '%s'\n", (const char *) type->name);
12686 printf(" fireErrors : %d\n", fireErrors);
12687 printf(" applyFacets: %d\n", applyFacets);
12688#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000012689 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
12690 if (memberLink == NULL) {
12691 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12692 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012693 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012694 type->name, NULL);
12695 ret = -1;
12696 }
12697 if (ret == 0) {
12698 while (memberLink != NULL) {
12699 ctxt->type = memberLink->type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012700 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012701 if ((ret <= 0) || (ret == 0))
12702 break;
12703 memberLink = memberLink->next;
12704 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012705 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012706 if (ret < 0) {
12707 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12708 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012710 type->name, NULL);
12711 } else if (ret > 0) {
12712 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012713 if (fireErrors)
12714 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12715 }
12716 }
12717 /*
12718 * Apply facets (pattern, enumeration).
12719 */
12720 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
12721 int mws;
12722 /*
12723 * The normalization behavior of ·union· types is controlled by
12724 * the value of whiteSpace on that one of the ·memberTypes·
12725 * against which the ·union· is successfully validated.
12726 */
12727 if (normValue != NULL) {
12728 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12729 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12730 "the value was already normalized for the union simple "
12731 "type '%s'.\n", type->name, NULL);
12732 }
12733 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
12734 if (mws > ctxt->valueWS) {
12735 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
12736 normValue = xmlSchemaCollapseString(value);
12737 else
12738 normValue = xmlSchemaWhiteSpaceReplace(value);
12739 if (normValue != NULL)
12740 value = (const xmlChar *) normValue;
12741 }
12742
12743 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12744 value, 0, fireErrors);
12745 if (ret < 0) {
12746 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12747 "Internal error: xmlSchemaValidateSimpleTypeValue, "
12748 "validating facets of union simple type '%s'\n",
12749 type->name, NULL);
12750 } else if (ret > 0) {
12751 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
12752 /*
12753 if (fireErrors)
12754 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
12755 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012756 }
12757 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012758 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012759 ctxt->type = type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012760 ctxt->valueWS = wtsp;
12761 if (normValue != NULL)
12762 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012763 return (ret);
12764}
12765
12766/**
12767 * xmlSchemaValidateSimpleTypeElement:
12768 * @ctxt: a schema validation context
12769 * @node: the element node to be validated.
12770 *
12771 * Validate the element against a simple type.
12772 *
12773 * Returns 0 if the element is valid, a positive error code
12774 * number otherwise and -1 in case of an internal or API error.
12775 */
12776static int
12777xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12778{
12779 xmlNodePtr child;
12780 xmlSchemaTypePtr type;
12781 xmlAttrPtr attr;
12782 int ret;
12783 xmlChar *value;
12784
12785
12786 child = ctxt->node;
12787 type = ctxt->type;
12788
12789 if ((ctxt == NULL) || (type == NULL)) {
12790 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12791 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
12792 node->name, NULL);
12793 return (-1);
12794 }
12795
12796 /*
12797 * Only text and text based entities references shall be found there
12798 */
12799 ret = xmlSchemaValidateCheckNodeList(child);
12800 if (ret < 0) {
12801 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12802 "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
12803 node->name, NULL);
12804 return (-1);
12805 } else if (ret == 0) {
12806 /* 3.1.2 The element information item must have no element
12807 * information item [children].
12808 */
12809 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012810 "Element '%s' must have no element children.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012811 node->name, NULL);
12812 return (-1);
12813 }
12814 /*
12815 * Validation Rule: Element Locally Valid (Type): 3.1.1
12816 */
12817 attr = node->properties;
12818 while (attr != NULL) {
12819 if ((attr->ns == NULL) ||
12820 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
12821 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
12822 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
12823 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
12824 (!xmlStrEqual
12825 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
12826 xmlSchemaVErr(ctxt, node,
12827 XML_SCHEMAV_CVC_TYPE_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012828 "The attributes of element '%s' must be empty, excepting "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012829 "those whose namespace name is identical to "
12830 "http://www.w3.org/2001/XMLSchema-instance and whose local "
12831 "name is one of type, nil, schemaLocation or "
12832 "noNamespaceSchemaLocation.\n",
12833 node->name, attr->name);
12834 return (ctxt->err);
12835 }
12836 attr = attr->next;
12837 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012838 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
12839 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
12840 value = xmlNodeGetContent(child);
12841 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
12842 if (value != NULL)
12843 xmlFree(value);
12844 ctxt->type = type;
12845 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012846 return (ret);
12847}
Daniel Veillard4255d502002-04-16 15:50:10 +000012848
12849/**
12850 * xmlSchemaValidateElementType:
12851 * @ctxt: a schema validation context
12852 * @node: the top node.
12853 *
12854 * Validate the content of an element type.
12855 * Validation Rule: Element Locally Valid (Complex Type)
12856 *
12857 * Returns 0 if the element is schemas valid, a positive error code
12858 * number otherwise and -1 in case of internal or API error.
12859 */
12860static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012861xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12862{
Daniel Veillard4255d502002-04-16 15:50:10 +000012863 xmlNodePtr child;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012864 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000012865 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000012866 int ret;
12867 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
12868
Daniel Veillard01fa6152004-06-29 17:04:39 +000012869 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000012870 /*
12871 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
12872 * go in here as well.
12873 */
12874
12875 /* TODO: Is this one called always with an element declaration as the
12876 * context's type?
12877 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012878
12879 oldregexp = ctxt->regexp;
12880
12881 child = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012882 decl = (xmlSchemaElementPtr) ctxt->type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012883
Daniel Veillardc0826a72004-08-10 14:17:33 +000012884 if ((ctxt == NULL) || (decl == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000012885 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12886 "Internal error: xmlSchemaValidateElementType\n",
12887 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012888 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012889 }
12890 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012891 if (decl->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +000012892 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
12893 "Element %s: missing child %s\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012894 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012895 }
12896 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012897 }
12898
12899 /*
12900 * Verify the element matches
12901 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012902 if (!xmlStrEqual(child->name, decl->name)) {
William M. Bracke7091952004-05-11 15:09:58 +000012903 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
12904 "Element %s: missing child %s found %s\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012905 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012906 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012907 }
12908 /*
12909 * Verify the attributes
12910 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012911 /*
12912 * TODO: This "attrTop" thing is not needed any more.
12913 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012914 attrs = ctxt->attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012915 attrTop = ctxt->attrTop;
12916 xmlSchemaRegisterAttributes(ctxt, child->properties);
12917 xmlSchemaValidateAttributes(ctxt, child, decl->subtypes);
12918 if (ctxt->attr != NULL)
12919 xmlSchemaFreeAttributeStates(ctxt->attr);
12920 ctxt->attr = attrs;
12921 ctxt->attrTop = attrTop;
Daniel Veillard3646d642004-06-02 19:19:14 +000012922
Daniel Veillard4255d502002-04-16 15:50:10 +000012923 /*
12924 * Verify the element content recursively
Daniel Veillardc0826a72004-08-10 14:17:33 +000012925 */
Daniel Veillard4255d502002-04-16 15:50:10 +000012926 oldregexp = ctxt->regexp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012927 /*
12928 * FIXME TODO: This one creates a regexp even if no content
12929 * model was defined. Somehow ->contModel is always not NULL
12930 * for complex types, even if they are empty.
12931 */
12932 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012933 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
12934 (xmlRegExecCallbacks)
12935 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012936#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012937 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012938#endif
12939 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012940 xmlSchemaValidateType(ctxt, child, decl, decl->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000012941
12942 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012943 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012944#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012945 xmlGenericError(xmlGenericErrorContext,
12946 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000012947#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012948 if (ret == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012949 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
12950 node, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012951 } else if (ret < 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012952 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
12953 node, "The element content is not valid", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012954#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012955 } else {
12956 xmlGenericError(xmlGenericErrorContext,
12957 "Element %s content check succeeded\n",
12958 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012959
12960#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012961 }
12962 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000012963 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012964 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000012965 ctxt->node = child;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012966 ctxt->type = (xmlSchemaTypePtr) decl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012967 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012968}
12969
Daniel Veillard01fa6152004-06-29 17:04:39 +000012970#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +000012971/**
12972 * xmlSchemaValidateBasicType:
12973 * @ctxt: a schema validation context
12974 * @node: the top node.
12975 *
12976 * Validate the content of an element expected to be a basic type type
12977 *
12978 * Returns 0 if the element is schemas valid, a positive error code
12979 * number otherwise and -1 in case of internal or API error.
12980 */
12981static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012982xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12983{
Daniel Veillard4255d502002-04-16 15:50:10 +000012984 int ret;
12985 xmlNodePtr child, cur;
12986 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012987 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +000012988
12989 child = ctxt->node;
12990 type = ctxt->type;
12991
12992 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000012993 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12994 "Internal error: xmlSchemaValidateBasicType\n",
12995 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012996 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012997 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012998 if (type->type != XML_SCHEMA_TYPE_BASIC) {
12999 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
13000 "Internal error: xmlSchemaValidateBasicType, "
13001 "the given type is not a built-in type.\n",
13002 node->name, NULL);
13003 return (-1);
13004 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013005 /*
13006 * First check the content model of the node.
13007 */
13008 cur = child;
13009 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013010 switch (cur->type) {
13011 case XML_TEXT_NODE:
13012 case XML_CDATA_SECTION_NODE:
13013 case XML_PI_NODE:
13014 case XML_COMMENT_NODE:
13015 case XML_XINCLUDE_START:
13016 case XML_XINCLUDE_END:
13017 break;
13018 case XML_ENTITY_REF_NODE:
13019 case XML_ENTITY_NODE:
13020 TODO break;
13021 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +000013022 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
13023 "Element %s: child %s should not be present\n",
13024 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013025 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013026 case XML_ATTRIBUTE_NODE:
13027 case XML_DOCUMENT_NODE:
13028 case XML_DOCUMENT_TYPE_NODE:
13029 case XML_DOCUMENT_FRAG_NODE:
13030 case XML_NOTATION_NODE:
13031 case XML_HTML_DOCUMENT_NODE:
13032 case XML_DTD_NODE:
13033 case XML_ELEMENT_DECL:
13034 case XML_ATTRIBUTE_DECL:
13035 case XML_ENTITY_DECL:
13036 case XML_NAMESPACE_DECL:
13037#ifdef LIBXML_DOCB_ENABLED
13038 case XML_DOCB_DOCUMENT_NODE:
13039#endif
William M. Bracke7091952004-05-11 15:09:58 +000013040 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
13041 "Element %s: node type of node unexpected here\n",
13042 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013043 return (ctxt->err);
13044 }
13045 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013046 }
13047 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013048 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013049 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013050 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013051
13052 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013053 xmlSchemaFreeValue(ctxt->value);
13054 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013055 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013056
Daniel Veillard4255d502002-04-16 15:50:10 +000013057 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
Daniel Veillard01fa6152004-06-29 17:04:39 +000013058
Daniel Veillard4255d502002-04-16 15:50:10 +000013059 if (value != NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013060 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +000013061 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +000013062 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
13063 "Element %s: failed to validate basic type %s\n",
13064 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013065 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013066 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013067}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013068#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013069
13070/**
Daniel Veillardc0826a72004-08-10 14:17:33 +000013071 * xmlSchemaValidateAnyInternal:
13072 * @ctxt: a schema validation context
13073 * @node: the top node.
13074 *
13075 * Represents the recursive portion of xmlSchemaValidateAny. Not
13076 * intended to be used by other functions.
13077 *
13078 * Returns 0 if the element is valid, a positive error code
13079 * number otherwise and -1 in case of an internal error.
13080 */
13081static int
13082xmlSchemaValidateAnyInternal(xmlSchemaValidCtxtPtr ctxt,
13083 xmlSchemaWildcardPtr wild,
13084 xmlNodePtr node)
13085{
13086 const xmlChar *uri;
13087 int ret = 0;
13088 xmlNodePtr child;
13089
13090 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
13091 xmlSchemaElementPtr decl = NULL;
13092
13093 if (node->ns != NULL)
13094 decl = xmlHashLookup3(ctxt->schema->elemDecl,
13095 node->name, node->ns->href, NULL);
13096 else
13097 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13098 if (decl != NULL) {
13099 ctxt->node = node;
13100 ctxt->type = (xmlSchemaTypePtr) decl;
13101 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13102 if (ret < 0) {
13103 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
13104 "Internal error: xmlSchemaValidateAnyInternal, "
13105 "validating an element in the context of a wildcard.",
13106 NULL, NULL);
13107 } else if (ret > 0)
13108 return (ret);
13109 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
13110 /* TODO: Change to proper error code. */
13111 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAS_ERR_UNDECLAREDELEM,
13112 node, wild, "No matching element declaration found.");
13113 return (ctxt->err);
13114 }
13115 }
13116 if (node->children != NULL) {
13117 child = node->children;
13118 do {
13119 if (child->type == XML_ELEMENT_NODE) {
13120 if (child->ns != NULL)
13121 uri = child->ns->href;
13122 else
13123 uri = NULL;
13124 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
13125 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
13126 child, wild,
13127 "The namespace of the element is not allowed.");
13128 return (ctxt->err);
13129 }
13130 ret = xmlSchemaValidateAnyInternal(ctxt, wild, child);
13131 if (ret != 0)
13132 return (ret);
13133 }
13134 child = child->next;
13135 } while (child != NULL);
13136 }
13137 return (0);
13138}
13139
13140/**
13141 * xmlSchemaValidateAny:
13142 * @ctxt: a schema validation context
13143 *
13144 * Returns 0 if the element is valid, a positive error code
13145 * number otherwise and -1 in case of an internal or API error.
13146 */
13147static int
13148xmlSchemaValidateAny(xmlSchemaValidCtxtPtr ctxt)
13149{
13150 return(xmlSchemaValidateAnyInternal(ctxt,
13151 ctxt->type->attributeWildcard, ctxt->cur));
13152}
13153
13154/**
William M. Brack2f2a6632004-08-20 23:09:47 +000013155 * xmlSchemaValidateAnyTypeContent:
13156 * @ctxt: a schema validation context
13157 * @node: the current element
13158 *
13159 * This one validates the content of an element of the type
13160 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
13161 * thus elements in the subtree will be validated, if a corresponding
13162 * declaration in the schema exists.
13163 *
13164 * Returns 0 if the element and its subtree is valid, a positive error code
13165 * otherwise and -1 in case of an internal or API error.
13166 */
13167static int
13168xmlSchemaValidateAnyTypeContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13169{
13170 xmlNodePtr top = node;
13171 xmlSchemaTypePtr decl;
13172 int skipContent, ret;
13173
13174 if (node->children == NULL)
13175 return (0);
13176 node = node->children;
13177 while (node != NULL) {
13178 skipContent = 0;
13179 if (node->type == XML_ELEMENT_NODE) {
13180 /*
13181 * The process contents of the wildcard is "lax", thus
13182 * we need to validate the element if a declaration
13183 * exists.
13184 */
13185 if (node->ns != NULL)
13186 decl = xmlHashLookup3(ctxt->schema->elemDecl,
13187 node->name, node->ns->href, NULL);
13188 else
13189 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
13190
13191 if (decl != NULL) {
13192 ctxt->node = node;
13193 ctxt->type = (xmlSchemaTypePtr) decl;
13194 ret = xmlSchemaValidateElementType(ctxt, node->parent);
13195 if (ret < 0) {
13196 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
13197 "Internal error: xmlSchemaValidateAnyTypeContent, "
13198 "validating an element in the context of a wildcard.",
13199 NULL, NULL);
13200 return (ret);
13201 } else if (ret > 0)
13202 return (ret);
13203 skipContent = 1;
13204 }
13205 }
13206 /*
13207 * Browse the full subtree, deep first.
13208 */
13209 if ((skipContent == 0) && (node->children != NULL)) {
13210 /* deep first */
13211 node = node->children;
13212 } else if ((node != top) && (node->next != NULL)) {
13213 /* then siblings */
13214 node = node->next;
13215 } else if (node != top) {
13216 /* go up to parents->next if needed */
13217 while (node != top) {
13218 if (node->parent != NULL)
13219 node = node->parent;
13220 if ((node != top) && (node->next != NULL)) {
13221 node = node->next;
13222 break;
13223 }
13224 if (node->parent == NULL) {
13225 node = NULL;
13226 break;
13227 }
13228 }
13229 /* exit condition */
13230 if (node == top)
13231 node = NULL;
13232 } else
13233 break;
13234 }
13235 return (0);
13236}
13237
13238/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013239 * xmlSchemaValidateComplexType:
13240 * @ctxt: a schema validation context
13241 * @node: the top node.
13242 *
13243 * Validate the content of an element expected to be a complex type type
13244 * xmlschema-1.html#cvc-complex-type
13245 * Validation Rule: Element Locally Valid (Complex Type)
13246 *
13247 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000013248 * number otherwise and -1 in case of internal or API error.
13249 * Note on reported errors: Although it might be nice to report
13250 * the name of the simple/complex type, used to validate the content
13251 * of a node, it is quite unnecessary: for global defined types
13252 * the local name of the element is equal to the NCName of the type,
13253 * for local defined types it makes no sense to output the internal
13254 * computed name of the type. TODO: Instead, one should attach the
13255 * struct of the type involved to the error handler - this allows
13256 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000013257 */
13258static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013259xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13260{
Daniel Veillard4255d502002-04-16 15:50:10 +000013261 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013262 xmlSchemaTypePtr type;
13263 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000013264 const xmlChar *nsUri;
Daniel Veillard3646d642004-06-02 19:19:14 +000013265
Daniel Veillard4255d502002-04-16 15:50:10 +000013266 child = ctxt->node;
13267 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013268 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013269
Daniel Veillard4255d502002-04-16 15:50:10 +000013270 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013271 case XML_SCHEMA_CONTENT_EMPTY: {
13272 /*
13273 * 1 If the {content type} is empty, then the element information
13274 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000013275 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013276 /*
13277 * TODO: Is the entity stuff correct?
13278 */
13279 while (child != NULL) {
13280 if ((child->type == XML_ELEMENT_NODE) ||
13281 /*
13282 * TODO: Ask Daniel if this are all character nodes.
13283 */
13284 (child->type == XML_TEXT_NODE) ||
13285 (child->type == XML_CDATA_SECTION_NODE) ||
13286 (child->type == XML_ENTITY_REF_NODE) ||
13287 (child->type == XML_ENTITY_NODE)) {
13288 break;
13289 }
13290 child = child->next;
13291 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013292 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013293 xmlSchemaVComplexTypeErr(ctxt,
13294 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
13295 node, type,
13296 "Character or element content is not allowed, "
13297 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013298 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013299 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013300 }
13301 case XML_SCHEMA_CONTENT_ELEMENTS:
13302 case XML_SCHEMA_CONTENT_MIXED:
13303 while (child != NULL) {
13304 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013305 if (child->ns != NULL)
13306 nsUri = child->ns->href;
13307 else
13308 nsUri = NULL;
13309 ret = xmlRegExecPushString2(ctxt->regexp,
13310 child->name, nsUri, child);
13311#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000013312 if (ret < 0)
13313 xmlGenericError(xmlGenericErrorContext,
13314 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000013315 else
13316 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013317 " --> %s\n", child->name);
13318#endif
13319 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
13320 /*
13321 * TODO: Ask Daniel if this are all character nodes.
13322 */
13323 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
13324 (child->type == XML_ENTITY_NODE) ||
13325 (child->type == XML_ENTITY_REF_NODE) ||
13326 (child->type == XML_CDATA_SECTION_NODE))) {
13327 /*
13328 * 2.3 If the {content type} is element-only, then the
13329 * element information item has no character information
13330 * item [children] other than those whose [character
13331 * code] is defined as a white space in [XML 1.0 (Second
13332 * Edition)].
13333 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013334 xmlSchemaVComplexTypeErr(ctxt,
13335 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
13336 node, type,
13337 "Character content is not allowed, "
13338 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 break;
13340 }
13341 child = child->next;
13342 }
13343 break;
13344 case XML_SCHEMA_CONTENT_SIMPLE:
13345 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013346 xmlChar *value = NULL;
13347 /*
13348 * We hit a complexType with a simpleContent resolving
13349 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000013350 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013351 /*
13352 * 2.2 If the {content type} is a simple type definition,
13353 * then the element information item has no element
13354 * information item [children], and the ·normalized value·
13355 * of the element information item is ·valid· with respect
13356 * to that simple type definition as defined by String
13357 * Valid (§3.14.4).
13358 */
13359 child = node->children;
13360 while (child != NULL) {
13361 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013362 xmlSchemaVComplexTypeErr(ctxt,
13363 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13364 node, type,
13365 "Element content is not allowed, because "
13366 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013367 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13368 break;
13369 }
13370 child = child->next;
13371 }
13372 if (ret == 0) {
13373 /*
13374 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000013375 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013376 if (ctxt->node == NULL)
13377 value = NULL;
13378 else
13379 value = xmlNodeGetContent(node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013380 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013381 if (ret > 0) {
13382 /*
13383 * NOTE: Although an error will be reported by
13384 * xmlSchemaValidateSimpleTypeValue, the spec wants
13385 * a specific complex type error to be reported
13386 * additionally.
13387 */
13388 xmlSchemaVComplexTypeErr(ctxt,
13389 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13390 node, type,
13391 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013392 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13393 } else if (ret < 0) {
13394 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
13395 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013396 "Element '%s': Error while validating character "
13397 "content against complex type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013398 node->name, type->name);
13399 return (-1);
13400 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013401 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013402 if (ret == 0) {
13403 /*
13404 * Apply facets of the complexType. Be sure to pass the
13405 * built-in type to xmlSchemaValidateFacetsInternal.
13406 */
13407 /* TODO: I don't know yet if the facets of the simple type
13408 * are used, or if the facets, defined by this complex type,
13409 * are to be used only. This here applies both facet sets.
13410 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013411
13412 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13413 value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013415 xmlSchemaVComplexTypeErr(ctxt,
13416 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
13417 node, type,
13418 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
13420 } else if (ret < 0) {
13421 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
13422 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013423 "Element '%s': Error while validating character "
13424 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 "apply facets.\n",
13426 type->name, NULL);
13427 }
13428 }
13429 if (value != NULL)
13430 xmlFree(value);
13431 /* TODO: facets */
13432 break;
13433 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013434 default:
13435 TODO xmlGenericError(xmlGenericErrorContext,
13436 "unimplemented content type %d\n",
13437 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000013438 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013440 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013441}
13442
13443/**
13444 * xmlSchemaValidateContent:
13445 * @ctxt: a schema validation context
13446 * @elem: an element
13447 * @type: the type declaration
13448 *
13449 * Validate the content of an element against the type.
13450 *
13451 * Returns 0 if the element is schemas valid, a positive error code
13452 * number otherwise and -1 in case of internal or API error.
13453 */
13454static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013455xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
13456{
Daniel Veillard4255d502002-04-16 15:50:10 +000013457 xmlSchemaTypePtr type;
13458
Daniel Veillard4255d502002-04-16 15:50:10 +000013459 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013460 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000013461
13462 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013463 case XML_SCHEMA_TYPE_ANY:
Daniel Veillardc0826a72004-08-10 14:17:33 +000013464 xmlSchemaValidateAny(ctxt);
13465 ctxt->type = type;
13466 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013467 case XML_SCHEMA_TYPE_COMPLEX:
13468 xmlSchemaValidateComplexType(ctxt, node);
13469 break;
13470 case XML_SCHEMA_TYPE_ELEMENT:{
13471 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
13472
13473 /*
13474 * Handle element reference here
13475 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013476 /*
13477 * TODO: This should be removed, since checks for
13478 * consistence should not be done during validation.
13479 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013480 if (decl->ref != NULL) {
13481 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013482 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
13483 "Internal error: element reference %s "
13484 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013485 return (-1);
13486 }
13487 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
13488 decl = decl->refDecl;
13489 }
William M. Bracke7091952004-05-11 15:09:58 +000013490 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013491 xmlSchemaValidateElementType(ctxt, node);
13492 ctxt->type = type;
13493 break;
13494 }
13495 case XML_SCHEMA_TYPE_BASIC:
William M. Brack2f2a6632004-08-20 23:09:47 +000013496 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
13497 xmlSchemaValidateAnyTypeContent(ctxt, node);
13498 else
13499 xmlSchemaValidateSimpleTypeElement(ctxt, node);
13500 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 case XML_SCHEMA_TYPE_SIMPLE:
13502 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013503 break;
13504 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013506 case XML_SCHEMA_TYPE_SEQUENCE:
13507 TODO break;
13508 case XML_SCHEMA_TYPE_CHOICE:
13509 TODO break;
13510 case XML_SCHEMA_TYPE_ALL:
13511 TODO break;
13512 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13513 TODO break;
13514 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13515 TODO break;
13516 case XML_SCHEMA_TYPE_UR:
13517 TODO break;
13518 case XML_SCHEMA_TYPE_RESTRICTION:
13519 /*xmlSchemaValidateRestrictionType(ctxt, node); */
13520 TODO break;
13521 case XML_SCHEMA_TYPE_EXTENSION:
13522 TODO break;
13523 case XML_SCHEMA_TYPE_ATTRIBUTE:
13524 TODO break;
13525 case XML_SCHEMA_TYPE_GROUP:
13526 TODO break;
13527 case XML_SCHEMA_TYPE_NOTATION:
13528 TODO break;
13529 case XML_SCHEMA_TYPE_LIST:
13530 TODO break;
13531 case XML_SCHEMA_TYPE_UNION:
13532 TODO break;
13533 case XML_SCHEMA_FACET_MININCLUSIVE:
13534 TODO break;
13535 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13536 TODO break;
13537 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13538 TODO break;
13539 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13540 TODO break;
13541 case XML_SCHEMA_FACET_TOTALDIGITS:
13542 TODO break;
13543 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13544 TODO break;
13545 case XML_SCHEMA_FACET_PATTERN:
13546 TODO break;
13547 case XML_SCHEMA_FACET_ENUMERATION:
13548 TODO break;
13549 case XML_SCHEMA_FACET_WHITESPACE:
13550 TODO break;
13551 case XML_SCHEMA_FACET_LENGTH:
13552 TODO break;
13553 case XML_SCHEMA_FACET_MAXLENGTH:
13554 TODO break;
13555 case XML_SCHEMA_FACET_MINLENGTH:
13556 TODO break;
13557 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13558 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000013559 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
13560 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000013561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013562
13563 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013564 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013565 ctxt->node = ctxt->node->next;
13566 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013567 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013568}
13569
13570/**
13571 * xmlSchemaValidateType:
13572 * @ctxt: a schema validation context
13573 * @elem: an element
13574 * @type: the list of type declarations
13575 *
13576 * Validate the content of an element against the types.
13577 *
13578 * Returns 0 if the element is schemas valid, a positive error code
13579 * number otherwise and -1 in case of internal or API error.
13580 */
13581static int
13582xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013583 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
13584{
Daniel Veillard4255d502002-04-16 15:50:10 +000013585 xmlChar *nil;
13586
Daniel Veillard2db8c122003-07-08 12:16:59 +000013587 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013588 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000013589
Daniel Veillard3646d642004-06-02 19:19:14 +000013590 /* This one is called by "xmlSchemaValidateElementType" and
13591 * "xmlSchemaValidateElement".
13592 */
13593
Daniel Veillard4255d502002-04-16 15:50:10 +000013594 /*
13595 * 3.3.4 : 2
13596 */
13597 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +000013598 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
13599 "Element declaration %s is abstract\n",
13600 elemDecl->name, NULL);
13601 /* Changed, since the element declaration is abstract and not
13602 * the element itself. */
13603 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
13604 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013605 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013606 }
13607 /*
13608 * 3.3.4: 3
13609 */
13610 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
13611 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013612 /* 3.3.4: 3.2 */
13613 if (xmlStrEqual(nil, BAD_CAST "true")) {
13614 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013615 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
13616 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013617 return (ctxt->err);
13618 }
13619 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
13620 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000013621 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
13622 "Empty element %s cannot get a fixed value\n",
13623 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013624 return (ctxt->err);
13625 }
13626 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013627 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013628 /* 3.3.4: 3.1 */
13629 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013630 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
13631 "Element %s with xs:nil but not nillable\n",
13632 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 xmlFree(nil);
13634 return (ctxt->err);
13635 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013636 }
13637
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013638 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000013639
13640 ctxt->type = elemDecl->subtypes;
13641 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013642 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013643 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013644}
13645
13646
13647/**
13648 * xmlSchemaValidateAttributes:
13649 * @ctxt: a schema validation context
13650 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000013651 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000013652 *
13653 * Validate the attributes of an element.
13654 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000013655 * 1. Existent, invalid attributes are reported in the form
13656 * "prefix:localName".
13657 * Reason: readability - it is easier to find the actual XML
13658 * representation of the attributes QName.
13659 * 2. Missing attributes are reported in the form
13660 * {"URI", "localName"}.
13661 * This is necessary, since the the prefix need not to be declared
13662 * at all, and thus is not computable.
13663 *
Daniel Veillard4255d502002-04-16 15:50:10 +000013664 * Returns 0 if the element is schemas valid, a positive error code
13665 * number otherwise and -1 in case of internal or API error.
13666 */
13667static int
Daniel Veillard3646d642004-06-02 19:19:14 +000013668xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013669{
Daniel Veillard3646d642004-06-02 19:19:14 +000013670 int ret;
13671 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000013672 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013673 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000013674 xmlSchemaAttributeLinkPtr attrUse;
13675 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013676 int found;
William M. Brack803812b2004-06-03 02:11:24 +000013677 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013678#ifdef DEBUG_ATTR_VALIDATION
13679 int redundant = 0;
13680#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013681
Daniel Veillardc0826a72004-08-10 14:17:33 +000013682 /*
13683 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
13684 * if we have an attribute reference or an attribute declaration.
13685 */
13686 /*
13687 * Allow all attributes if the type is anyType.
13688 */
13689 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
13690 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013691 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013692 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013693 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000013694 attrDecl = attrUse->attr;
13695#ifdef DEBUG_ATTR_VALIDATION
13696 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
13697 printf("attr use - use: %d\n", attrDecl->occurs);
13698#endif
13699 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
13700
13701 if (curState->decl == attrUse->attr) {
13702#ifdef DEBUG_ATTR_VALIDATION
13703 redundant = 1;
13704#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013705 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013706 attr = curState->attr;
13707#ifdef DEBUG_ATTR_VALIDATION
13708 printf("attr - name: %s\n", attr->name);
13709 if (attr->ns != NULL)
13710 printf("attr - ns: %s\n", attr->ns->href);
13711 else
13712 printf("attr - ns: none\n");
13713#endif
13714 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013715 if (attr == NULL)
13716 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013717 if (attrDecl->ref != NULL) {
13718 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013719 continue;
13720 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013721 if ((attrDecl->refNs == NULL) ||
13722 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013723 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013724 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013725 continue;
13726 }
13727 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013728 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013729 continue;
13730 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013731 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013732 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013733 if (attr->ns == NULL) {
13734 /*
William M. Bracke7091952004-05-11 15:09:58 +000013735 * accept an unqualified attribute only if the target
13736 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013737 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013738 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000013739 /*
13740 * This check was removed, since the target namespace
13741 * was evaluated during parsing and already took
13742 * "attributeFormDefault" into account.
13743 */
13744 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013745 continue;
13746 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000013747 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013748 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013749 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013750 attr->ns->href))
13751 continue;
13752 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013753 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013754#ifdef DEBUG_ATTR_VALIDATION
13755 printf("found\n");
13756#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013757 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000013758 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000013760
Daniel Veillard3646d642004-06-02 19:19:14 +000013761 if (attrDecl->subtypes == NULL) {
13762 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
13763 curState->decl = attrDecl;
William M. Bracke7091952004-05-11 15:09:58 +000013764 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
13765 "Internal error: attribute %s type not resolved\n",
13766 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013767 continue;
13768 }
13769 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013770 ctxt->type = attrDecl->subtypes;
13771 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013772 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000013773 if (ret != 0)
13774 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13775 else
13776 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13777 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013778 if (value != NULL) {
13779 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000013780 }
13781 }
13782 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
13783 xmlSchemaAttrStatePtr tmp;
13784
13785#ifdef DEBUG_ATTR_VALIDATION
13786 printf("required attr not found\n");
13787#endif
13788 /*
13789 * Add a new dummy attribute state.
13790 */
13791 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
13792 if (tmp == NULL) {
13793 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
13794 return (-1);
13795 }
13796 tmp->attr = NULL;
13797 tmp->state = XML_SCHEMAS_ATTR_MISSING;
13798 tmp->decl = attrDecl;
13799 tmp->next = NULL;
13800
13801 if (reqAttrStates == NULL) {
13802 reqAttrStates = tmp;
13803 reqAttrStatesTop = tmp;
13804 } else {
13805 reqAttrStatesTop->next = tmp;
13806 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013807 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013808
13809 }
13810 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013811 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013812 /*
13813 * Add required attributes to the attribute states of the context.
13814 */
13815 if (reqAttrStates != NULL) {
13816 if (ctxt->attr == NULL) {
13817 ctxt->attr = reqAttrStates;
13818 } else {
13819 ctxt->attrTop->next = reqAttrStates;
13820 }
13821 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013822 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013823 /*
13824 * Process wildcards.
13825 */
13826 if (type->attributeWildcard != NULL) {
13827#ifdef DEBUG_ATTR_VALIDATION
13828 xmlSchemaWildcardNsPtr ns;
13829 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013830 if (type->attributeWildcard->processContents ==
13831 XML_SCHEMAS_ANY_LAX)
13832 printf("processContents: lax\n");
13833 else if (type->attributeWildcard->processContents ==
13834 XML_SCHEMAS_ANY_STRICT)
13835 printf("processContents: strict\n");
13836 else
13837 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000013838 if (type->attributeWildcard->any)
13839 printf("type: any\n");
13840 else if (type->attributeWildcard->negNsSet != NULL) {
13841 printf("type: negated\n");
13842 if (type->attributeWildcard->negNsSet->value == NULL)
13843 printf("ns: (absent)\n");
13844 else
13845 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
13846 } else if (type->attributeWildcard->nsSet != NULL) {
13847 printf("type: set\n");
13848 ns = type->attributeWildcard->nsSet;
13849 while (ns != NULL) {
13850 if (ns->value == NULL)
13851 printf("ns: (absent)\n");
13852 else
13853 printf("ns: %s\n", ns->value);
13854 ns = ns->next;
13855 }
13856 } else
13857 printf("empty\n");
13858
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013859
13860#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000013861 curState = ctxt->attr;
13862 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013863 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
13864 if (curState->attr->ns != NULL)
13865 nsURI = curState->attr->ns->href;
13866 else
13867 nsURI = NULL;
13868 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
13869 nsURI)) {
13870 /*
13871 * Handle processContents.
13872 */
13873 if ((type->attributeWildcard->processContents ==
13874 XML_SCHEMAS_ANY_LAX) ||
13875 (type->attributeWildcard->processContents ==
13876 XML_SCHEMAS_ANY_STRICT)) {
13877
13878 attr = curState->attr;
13879 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
13880 attr->name, nsURI);
13881 if (attrDecl != NULL) {
13882 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013883 ctxt->cur = (xmlNodePtr) attr;
13884 ctxt->node = attr->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013885 ctxt->type = attrDecl->subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013886 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013887 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013888 if (ret != 0)
13889 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
13890 else
13891 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13892 curState->decl = attrDecl;
13893 if (value != NULL) {
13894 xmlFree(value);
13895 }
13896
13897 } else if (type->attributeWildcard->processContents ==
13898 XML_SCHEMAS_ANY_LAX) {
13899 curState->state = XML_SCHEMAS_ATTR_CHECKED;
13900 }
13901 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000013902 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000013903 }
13904 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013905 curState = curState->next;
13906 }
13907 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013908 /*
13909 * Report missing and illegal attributes.
13910 */
13911 if (ctxt->attr != NULL) {
13912 curState = ctxt->attr;
13913 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
13914 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
13915 attr = curState->attr;
13916 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
13917 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
13918 else if ((curState->state == XML_SCHEMAS_ATTR_UNKNOWN) ||
13919 /* TODO: "prohibited" won't ever be touched!. */
13920 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
13921 xmlSchemaVIllegalAttrErr(ctxt, attr);
13922 }
13923 curState = curState->next;
13924 }
13925 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013926#ifdef DEBUG_ATTR_VALIDATION
13927 if (redundant)
13928 xmlGenericError(xmlGenericErrorContext,
13929 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
13930 type->name);
13931#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013932 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013933}
13934
13935/**
13936 * xmlSchemaValidateElement:
13937 * @ctxt: a schema validation context
13938 * @elem: an element
13939 *
13940 * Validate an element in a tree
13941 *
13942 * Returns 0 if the element is schemas valid, a positive error code
13943 * number otherwise and -1 in case of internal or API error.
13944 */
13945static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013946xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
13947{
Daniel Veillard4255d502002-04-16 15:50:10 +000013948 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000013949 int ret;
13950 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013951
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013952 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013953 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13954 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013955 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013956 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13957 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013958 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013959 /*
13960 * This one is called by xmlSchemaValidateDocument and
13961 * xmlSchemaValidateAnyInernal.
13962 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013963
Daniel Veillard4255d502002-04-16 15:50:10 +000013964 /*
13965 * 3.3.4 : 1
13966 */
13967 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013968 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
13969 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013970 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013971 }
13972 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013973 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
13974 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013975 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013976 }
13977 /*
13978 * Verify the attributes
13979 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013980 attrs = ctxt->attr;
13981 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013982 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013983 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->subtypes);
13984 if (ctxt->attr != NULL)
13985 xmlSchemaFreeAttributeStates(ctxt->attr);
13986 ctxt->attr = attrs;
13987 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000013988 /*
13989 * Verify the element content recursively
13990 */
13991 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013992 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
13993 (xmlRegExecCallbacks)
13994 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013995#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013996 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013997#endif
13998 }
13999 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014000 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014001 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014002#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014003 xmlGenericError(xmlGenericErrorContext,
14004 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014005#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000014006 if (ret == 0) {
14007 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
14008 elem, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014009 } else if (ret < 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014010 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
14011 elem, "The element content is not valid", NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014012#ifdef DEBUG_CONTENT
Daniel Veillardc0826a72004-08-10 14:17:33 +000014013 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014014 xmlGenericError(xmlGenericErrorContext,
14015 "Element %s content check succeeded\n",
14016 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014017
14018#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014019 }
14020 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000014021 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014022 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014023}
14024
14025/**
14026 * xmlSchemaValidateDocument:
14027 * @ctxt: a schema validation context
14028 * @doc: a parsed document tree
14029 *
14030 * Validate a document tree in memory.
14031 *
14032 * Returns 0 if the document is schemas valid, a positive error code
14033 * number otherwise and -1 in case of internal or API error.
14034 */
14035static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014036xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14037{
Daniel Veillard4255d502002-04-16 15:50:10 +000014038 xmlNodePtr root;
14039 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040
Daniel Veillard4255d502002-04-16 15:50:10 +000014041 root = xmlDocGetRootElement(doc);
14042 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000014043 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
14044 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014045 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014046 }
William M. Bracke7091952004-05-11 15:09:58 +000014047
Daniel Veillard4255d502002-04-16 15:50:10 +000014048 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014049 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
14050 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014051 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014052 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
14053 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014054
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014055 /*
14056 * special case whe elementFormDefault is unqualified for top-level elem.
14057 */
Daniel Veillard3646d642004-06-02 19:19:14 +000014058 /* Removed, since elementFormDefault does not apply to top level
14059 * elements */
14060 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014061 if ((elemDecl == NULL) && (root->ns != NULL) &&
14062 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
14063 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
14064 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
14065 root->name, NULL, NULL);
14066 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014067 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000014068
Daniel Veillard4255d502002-04-16 15:50:10 +000014069 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000014070 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
14071 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014072 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000014073 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000014074 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014075 }
14076 /*
14077 * Okay, start the recursive validation
14078 */
14079 xmlSchemaValidateElement(ctxt, root);
14080
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014081 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014082}
14083
14084/************************************************************************
14085 * *
14086 * SAX Validation code *
14087 * *
14088 ************************************************************************/
14089
14090/************************************************************************
14091 * *
14092 * Validation interfaces *
14093 * *
14094 ************************************************************************/
14095
14096/**
14097 * xmlSchemaNewValidCtxt:
14098 * @schema: a precompiled XML Schemas
14099 *
14100 * Create an XML Schemas validation context based on the given schema
14101 *
14102 * Returns the validation context or NULL in case of error
14103 */
14104xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014105xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
14106{
Daniel Veillard4255d502002-04-16 15:50:10 +000014107 xmlSchemaValidCtxtPtr ret;
14108
14109 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
14110 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014111 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014112 return (NULL);
14113 }
14114 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014115 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000014116 ret->attrTop = NULL;
14117 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014118 return (ret);
14119}
14120
14121/**
14122 * xmlSchemaFreeValidCtxt:
14123 * @ctxt: the schema validation context
14124 *
14125 * Free the resources associated to the schema validation context
14126 */
14127void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014128xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
14129{
Daniel Veillard4255d502002-04-16 15:50:10 +000014130 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014131 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014132 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014133 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000014134 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014135 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000014136 xmlFree(ctxt);
14137}
14138
14139/**
14140 * xmlSchemaSetValidErrors:
14141 * @ctxt: a schema validation context
14142 * @err: the error function
14143 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000014144 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000014145 *
William M. Brack2f2a6632004-08-20 23:09:47 +000014146 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000014147 */
14148void
14149xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014150 xmlSchemaValidityErrorFunc err,
14151 xmlSchemaValidityWarningFunc warn, void *ctx)
14152{
Daniel Veillard4255d502002-04-16 15:50:10 +000014153 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014154 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014155 ctxt->error = err;
14156 ctxt->warning = warn;
14157 ctxt->userData = ctx;
14158}
14159
14160/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014161 * xmlSchemaGetValidErrors:
14162 * @ctxt: a XML-Schema validation context
14163 * @err: the error function result
14164 * @warn: the warning function result
14165 * @ctx: the functions context result
14166 *
14167 * Get the error and warning callback informations
14168 *
14169 * Returns -1 in case of error and 0 otherwise
14170 */
14171int
14172xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
14173 xmlSchemaValidityErrorFunc * err,
14174 xmlSchemaValidityWarningFunc * warn, void **ctx)
14175{
14176 if (ctxt == NULL)
14177 return (-1);
14178 if (err != NULL)
14179 *err = ctxt->error;
14180 if (warn != NULL)
14181 *warn = ctxt->warning;
14182 if (ctx != NULL)
14183 *ctx = ctxt->userData;
14184 return (0);
14185}
14186
14187/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014188 * xmlSchemaValidateDoc:
14189 * @ctxt: a schema validation context
14190 * @doc: a parsed document tree
14191 *
14192 * Validate a document tree in memory.
14193 *
14194 * Returns 0 if the document is schemas valid, a positive error code
14195 * number otherwise and -1 in case of internal or API error.
14196 */
14197int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014198xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
14199{
Daniel Veillard4255d502002-04-16 15:50:10 +000014200 int ret;
14201
14202 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014203 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014204
14205 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000014206 ctxt->err = 0;
14207 ctxt->nberrors = 0;
14208
Daniel Veillard4255d502002-04-16 15:50:10 +000014209 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014210 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000014211}
14212
14213/**
14214 * xmlSchemaValidateStream:
14215 * @ctxt: a schema validation context
14216 * @input: the input to use for reading the data
14217 * @enc: an optional encoding information
14218 * @sax: a SAX handler for the resulting events
14219 * @user_data: the context to provide to the SAX handler.
14220 *
14221 * Validate a document tree in memory.
14222 *
14223 * Returns 0 if the document is schemas valid, a positive error code
14224 * number otherwise and -1 in case of internal or API error.
14225 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014226int
Daniel Veillard4255d502002-04-16 15:50:10 +000014227xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014228 xmlParserInputBufferPtr input, xmlCharEncoding enc,
14229 xmlSAXHandlerPtr sax, void *user_data)
14230{
Daniel Veillard4255d502002-04-16 15:50:10 +000014231 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014232 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014233 ctxt->input = input;
14234 ctxt->enc = enc;
14235 ctxt->sax = sax;
14236 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014237 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014238}
14239
14240#endif /* LIBXML_SCHEMAS_ENABLED */