blob: c95caf056cf016f47970b2b3c5c386c1645f8bec [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
Daniel Veillard5a872412002-05-22 06:40:27 +000059#define XML_SCHEMAS_DEFAULT_NAMESPACE (const xmlChar *)"the default namespace"
60
Daniel Veillardc0826a72004-08-10 14:17:33 +000061#define XML_SCHEMAS_NO_NS (const xmlChar *) "##"
62
Daniel Veillard4255d502002-04-16 15:50:10 +000063/*
64 * The XML Schemas namespaces
65 */
66static const xmlChar *xmlSchemaNs = (const xmlChar *)
67 "http://www.w3.org/2001/XMLSchema";
68
69static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
70 "http://www.w3.org/2001/XMLSchema-instance";
71
Daniel Veillardc0826a72004-08-10 14:17:33 +000072static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
73 "Element decl.";
74static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
75 "Element ref.";
76static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
77 "Attribute decl.";
78static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
79 "Attribute ref.";
80static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
81 "ST";
82static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
83 "CT";
84
Daniel Veillard4255d502002-04-16 15:50:10 +000085#define IS_SCHEMA(node, type) \
86 ((node != NULL) && (node->ns != NULL) && \
87 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
88 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
89
Daniel Veillardc0826a72004-08-10 14:17:33 +000090#define FREE_AND_NULL(str) \
91 if (str != NULL) { \
92 xmlFree(str); \
93 str = NULL; \
94 }
95
96#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
97#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
98#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
99
Daniel Veillard4255d502002-04-16 15:50:10 +0000100#define XML_SCHEMAS_PARSE_ERROR 1
101
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000102#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
103
Daniel Veillard4255d502002-04-16 15:50:10 +0000104struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000105 void *userData; /* user specific data block */
106 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
107 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000108 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000109 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000110 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000111
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000112 xmlSchemaPtr topschema; /* The main schema */
113 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
114
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000115 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000116 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000117 int counter;
118
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000119 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000120 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000121 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000122
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000123 const char *buffer;
124 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000125
Daniel Veillard4255d502002-04-16 15:50:10 +0000126 /*
127 * Used to build complex element content models
128 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000129 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000130 xmlAutomataStatePtr start;
131 xmlAutomataStatePtr end;
132 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000133
134 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000135 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000136 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
137 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Daniel Veillard4255d502002-04-16 15:50:10 +0000138};
139
140
141#define XML_SCHEMAS_ATTR_UNKNOWN 1
142#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000143#define XML_SCHEMAS_ATTR_PROHIBITED 3
144#define XML_SCHEMAS_ATTR_MISSING 4
145#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
146#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Daniel Veillard4255d502002-04-16 15:50:10 +0000147
148typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
149typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
150struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000151 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000152 xmlAttrPtr attr;
153 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000154 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +0000155};
156
157/**
158 * xmlSchemaValidCtxt:
159 *
160 * A Schemas validation context
161 */
162
163struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000164 void *userData; /* user specific data block */
165 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
166 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000167 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000168
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000169 xmlSchemaPtr schema; /* The schema in use */
170 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000171 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000172 xmlCharEncoding enc;
173 xmlSAXHandlerPtr sax;
174 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000175
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr myDoc;
177 int err;
178 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000179
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000180 xmlNodePtr node;
181 xmlNodePtr cur;
182 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000183
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000184 xmlRegExecCtxtPtr regexp;
185 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186
Daniel Veillard3646d642004-06-02 19:19:14 +0000187 xmlSchemaAttrStatePtr attrTop;
188 /* xmlSchemaAttrStatePtr attrBase; */
189 /* int attrMax; */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000190 xmlSchemaAttrStatePtr attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000191 xmlNodePtr scope;
192 int valueWS;
Daniel Veillard4255d502002-04-16 15:50:10 +0000193};
194
Daniel Veillard1d913862003-11-21 00:28:39 +0000195/*
196 * These are the entries in the schemas importSchemas hash table
197 */
198typedef struct _xmlSchemaImport xmlSchemaImport;
199typedef xmlSchemaImport *xmlSchemaImportPtr;
200struct _xmlSchemaImport {
201 const xmlChar *schemaLocation;
202 xmlSchemaPtr schema;
203};
Daniel Veillard4255d502002-04-16 15:50:10 +0000204
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000205/*
206 * These are the entries associated to includes in a schemas
207 */
208typedef struct _xmlSchemaInclude xmlSchemaInclude;
209typedef xmlSchemaInclude *xmlSchemaIncludePtr;
210struct _xmlSchemaInclude {
211 xmlSchemaIncludePtr next;
212
213 const xmlChar *schemaLocation;
214 xmlDocPtr doc;
215};
216
Daniel Veillard4255d502002-04-16 15:50:10 +0000217/************************************************************************
218 * *
219 * Some predeclarations *
220 * *
221 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000222
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000223static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
224 xmlSchemaPtr schema,
225 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000226static void
227xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
228 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
229static const char *
230xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
231static int
232xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
233 const xmlChar *value,
234 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000235 int applyFacets,
236 int normalize);
William M. Brack87640d52004-04-17 14:58:15 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238/************************************************************************
239 * *
240 * Datatype error handlers *
241 * *
242 ************************************************************************/
243
244/**
245 * xmlSchemaPErrMemory:
246 * @node: a context node
247 * @extra: extra informations
248 *
249 * Handle an out of memory condition
250 */
251static void
252xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
253 const char *extra, xmlNodePtr node)
254{
255 if (ctxt != NULL)
256 ctxt->nberrors++;
257 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
258 extra);
259}
260
261/**
262 * xmlSchemaPErr:
263 * @ctxt: the parsing context
264 * @node: the context node
265 * @error: the error code
266 * @msg: the error message
267 * @str1: extra data
268 * @str2: extra data
269 *
270 * Handle a parser error
271 */
272static void
273xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
274 const char *msg, const xmlChar * str1, const xmlChar * str2)
275{
276 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000277 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000278 void *data = NULL;
279
280 if (ctxt != NULL) {
281 ctxt->nberrors++;
282 channel = ctxt->error;
283 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000284 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000285 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000286 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000287 error, XML_ERR_ERROR, NULL, 0,
288 (const char *) str1, (const char *) str2, NULL, 0, 0,
289 msg, str1, str2);
290}
291
292/**
293 * xmlSchemaPErr2:
294 * @ctxt: the parsing context
295 * @node: the context node
296 * @node: the current child
297 * @error: the error code
298 * @msg: the error message
299 * @str1: extra data
300 * @str2: extra data
301 *
302 * Handle a parser error
303 */
304static void
305xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
306 xmlNodePtr child, int error,
307 const char *msg, const xmlChar * str1, const xmlChar * str2)
308{
309 if (child != NULL)
310 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
311 else
312 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
313}
314
Daniel Veillard01fa6152004-06-29 17:04:39 +0000315
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000316/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000317 * xmlSchemaPErrExt:
318 * @ctxt: the parsing context
319 * @node: the context node
320 * @error: the error code
321 * @strData1: extra data
322 * @strData2: extra data
323 * @strData3: extra data
324 * @msg: the message
325 * @str1: extra parameter for the message display
326 * @str2: extra parameter for the message display
327 * @str3: extra parameter for the message display
328 * @str4: extra parameter for the message display
329 * @str5: extra parameter for the message display
330 *
331 * Handle a parser error
332 */
333static void
334xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
335 const xmlChar * strData1, const xmlChar * strData2,
336 const xmlChar * strData3, const char *msg, const xmlChar * str1,
337 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
338 const xmlChar * str5)
339{
340
341 xmlGenericErrorFunc channel = NULL;
342 xmlStructuredErrorFunc schannel = NULL;
343 void *data = NULL;
344
345 if (ctxt != NULL) {
346 ctxt->nberrors++;
347 channel = ctxt->error;
348 data = ctxt->userData;
349 schannel = ctxt->serror;
350 }
351 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
352 error, XML_ERR_ERROR, NULL, 0,
353 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000354 (const char *) strData3, 0, 0, msg, str1, str2,
355 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000356}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000357
Daniel Veillard3646d642004-06-02 19:19:14 +0000358
359/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000360 * xmlSchemaVTypeErrMemory:
361 * @node: a context node
362 * @extra: extra informations
363 *
364 * Handle an out of memory condition
365 */
366static void
367xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
368 const char *extra, xmlNodePtr node)
369{
370 if (ctxt != NULL) {
371 ctxt->nberrors++;
372 ctxt->err = XML_SCHEMAS_ERR_INTERNAL;
373 }
374 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
375 extra);
376}
377
378/**
379 * xmlSchemaVErr3:
380 * @ctxt: the validation context
381 * @node: the context node
382 * @error: the error code
383 * @msg: the error message
384 * @str1: extra data
385 * @str2: extra data
386 * @str3: extra data
387 *
388 * Handle a validation error
389 */
390static void
391xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
392 const char *msg, const xmlChar *str1, const xmlChar *str2,
393 const xmlChar *str3)
394{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000395 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000396 xmlGenericErrorFunc channel = NULL;
397 void *data = NULL;
398
399 if (ctxt != NULL) {
400 ctxt->nberrors++;
401 ctxt->err = error;
402 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000403 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000404 data = ctxt->userData;
405 }
406 /* reajust to global error numbers */
407 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000408 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000409 error, XML_ERR_ERROR, NULL, 0,
410 (const char *) str1, (const char *) str2,
411 (const char *) str3, 0, 0,
412 msg, str1, str2, str3);
413}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000414
415/**
416 * xmlSchemaVErrExt:
417 * @ctxt: the validation context
418 * @node: the context node
419 * @error: the error code
420 * @msg: the message
421 * @str1: extra parameter for the message display
422 * @str2: extra parameter for the message display
423 * @str3: extra parameter for the message display
424 * @str4: extra parameter for the message display
425 * @str5: extra parameter for the message display
426 *
427 * Handle a validation error
428 */
429static void
430xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
431 const char *msg, const xmlChar * str1,
432 const xmlChar * str2, const xmlChar * str3,
433 const xmlChar * str4, const xmlChar * str5)
434{
435 xmlStructuredErrorFunc schannel = NULL;
436 xmlGenericErrorFunc channel = NULL;
437 void *data = NULL;
438
439 if (ctxt != NULL) {
440 ctxt->nberrors++;
441 ctxt->err = error;
442 channel = ctxt->error;
443 schannel = ctxt->serror;
444 data = ctxt->userData;
445 }
446 /* reajust to global error numbers */
447 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
448 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
449 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
450 msg, str1, str2, str3, str4, str5);
451}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000452/**
453 * xmlSchemaVErr:
454 * @ctxt: the validation context
455 * @node: the context node
456 * @error: the error code
457 * @msg: the error message
458 * @str1: extra data
459 * @str2: extra data
460 *
461 * Handle a validation error
462 */
463static void
464xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
465 const char *msg, const xmlChar * str1, const xmlChar * str2)
466{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000467 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000468 xmlGenericErrorFunc channel = NULL;
469 void *data = NULL;
470
471 if (ctxt != NULL) {
472 ctxt->nberrors++;
473 ctxt->err = error;
474 channel = ctxt->error;
475 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000476 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000477 }
478 /* reajust to global error numbers */
479 error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000480 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000481 error, XML_ERR_ERROR, NULL, 0,
482 (const char *) str1, (const char *) str2, NULL, 0, 0,
483 msg, str1, str2);
484}
Daniel Veillard4255d502002-04-16 15:50:10 +0000485
Daniel Veillardc0826a72004-08-10 14:17:33 +0000486/**
487 * xmlSchemaGetOnymousTypeName:
488 * @attr: the attribute declaration/use
489 *
490 * Returns the name of the attribute; if the attribute
491 * is a reference, the name of the referenced global type will be returned.
492 */
493static const xmlChar *
494xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
495{
496 if (attr->ref != NULL)
497 return(attr->ref);
498 else
499 return(attr->name);
500}
501
502/**
503 * xmlSchemaGetOnymousTargetNsURI:
504 * @type: the type (element or attribute)
505 *
506 * Returns the target namespace URI of the type; if the type is a reference,
507 * the target namespace of the referenced type will be returned.
508 */
509static const xmlChar *
510xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
511{
512 if (attr->ref != NULL)
513 return (attr->refNs);
514 else
515 return(attr->targetNamespace);
516}
517
518/**
519 * xmlSchemaFormatNsUriLocal:
520 * @buf: the string buffer
521 * @uri: the namespace URI
522 * @local: the local name
523 *
524 * Returns a representation of the given URI used
525 * for error reports.
526 *
527 * Returns an empty string, if @ns is NULL, a formatted
528 * string otherwise.
529 */
530static const xmlChar*
531xmlSchemaFormatNsUriLocal(xmlChar **buf,
532 const xmlChar *uri, const xmlChar *local)
533{
534 if (*buf != NULL)
535 xmlFree(*buf);
536 if (uri == NULL) {
537 *buf = xmlStrdup(BAD_CAST "{'");
538 *buf = xmlStrcat(*buf, local);
539 } else {
540 *buf = xmlStrdup(BAD_CAST "{'");
541 *buf = xmlStrcat(*buf, uri);
542 *buf = xmlStrcat(*buf, BAD_CAST "', '");
543 *buf = xmlStrcat(*buf, local);
544 }
545 *buf = xmlStrcat(*buf, BAD_CAST "'}");
546 return ((const xmlChar *) *buf);
547}
548
549/**
550 * xmlSchemaFormatNsPrefixLocal:
551 * @buf: the string buffer
552 * @ns: the namespace
553 * @local: the local name
554 *
555 * Returns a representation of the given URI used
556 * for error reports.
557 *
558 * Returns an empty string, if @ns is NULL, a formatted
559 * string otherwise.
560 */
561static const xmlChar*
562xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
563 xmlNsPtr ns, const xmlChar *local)
564{
565 if (*buf != NULL) {
566 xmlFree(*buf);
567 *buf = NULL;
568 }
569 if ((ns == NULL) || (ns->prefix == NULL))
570 return(local);
571 else {
572 *buf = xmlStrdup(ns->prefix);
573 *buf = xmlStrcat(*buf, BAD_CAST ":");
574 *buf = xmlStrcat(*buf, local);
575 }
576 return ((const xmlChar *) *buf);
577}
578
579/**
580 * xmlSchemaFormatItemForReport:
581 * @buf: the string buffer
582 * @itemDes: the designation of the item
583 * @itemName: the name of the item
584 * @item: the item as an object
585 * @itemNode: the node of the item
586 * @local: the local name
587 * @parsing: if the function is used during the parse
588 *
589 * Returns a representation of the given item used
590 * for error reports.
591 *
592 * The following order is used to build the resulting
593 * designation if the arguments are not NULL:
594 * 1a. If itemDes not NULL -> itemDes
595 * 1b. If (itemDes not NULL) and (itemName not NULL)
596 * -> itemDes + itemName
597 * 2. If the preceding was NULL and (item not NULL) -> item
598 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
599 *
600 * If the itemNode is an attribute node, the name of the attribute
601 * will be appended to the result.
602 *
603 * Returns the formatted string and sets @buf to the resulting value.
604 */
605static xmlChar*
606xmlSchemaFormatItemForReport(xmlChar **buf,
607 const xmlChar *itemDes,
608 xmlSchemaTypePtr item,
609 xmlNodePtr itemNode,
610 int parsing)
611{
612 xmlChar *str = NULL;
613
614 if (*buf != NULL) {
615 xmlFree(*buf);
616 *buf = NULL;
617 }
618
619 if (itemDes != NULL)
620 *buf = xmlStrdup(itemDes);
621 else if (item != NULL) {
622 if (item->type == XML_SCHEMA_TYPE_BASIC) {
623 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
624 *buf = xmlStrdup(BAD_CAST "'anyType'");
625 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
626 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
627 else {
628 /* *buf = xmlStrdup(BAD_CAST "bi "); */
629 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
630 *buf = xmlStrdup(BAD_CAST "'");
631 *buf = xmlStrcat(*buf, item->name);
632 *buf = xmlStrcat(*buf, BAD_CAST "'");
633 }
634 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
635 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
636 *buf = xmlStrdup(xmlSchemaElemDesST);
637 *buf = xmlStrcat(*buf, BAD_CAST " '");
638 *buf = xmlStrcat(*buf, item->name);
639 *buf = xmlStrcat(*buf, BAD_CAST "'");
640 } else {
641 *buf = xmlStrdup(xmlSchemaElemDesST);
642 *buf = xmlStrcat(*buf, BAD_CAST " local");
643 }
644 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
645 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
646 *buf = xmlStrdup(xmlSchemaElemDesCT);
647 *buf = xmlStrcat(*buf, BAD_CAST " '");
648 *buf = xmlStrcat(*buf, item->name);
649 *buf = xmlStrcat(*buf, BAD_CAST "'");
650 } else {
651 *buf = xmlStrdup(xmlSchemaElemDesCT);
652 *buf = xmlStrcat(*buf, BAD_CAST " local");
653 }
654 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
655 xmlSchemaAttributePtr attr;
656
657 attr = (xmlSchemaAttributePtr) item;
658 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
659 (attr->ref == NULL)) {
660 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
661 *buf = xmlStrcat(*buf, BAD_CAST " '");
662 *buf = xmlStrcat(*buf, attr->name);
663 *buf = xmlStrcat(*buf, BAD_CAST "'");
664 } else {
665 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
666 *buf = xmlStrcat(*buf, BAD_CAST " '");
667 *buf = xmlStrcat(*buf, attr->refPrefix);
668 *buf = xmlStrcat(*buf, BAD_CAST ":");
669 *buf = xmlStrcat(*buf, attr->ref);
670 *buf = xmlStrcat(*buf, BAD_CAST "'");
671 }
672 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
673 xmlSchemaElementPtr elem;
674
675 elem = (xmlSchemaElementPtr) item;
676 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
677 (elem->ref == NULL)) {
678 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
679 *buf = xmlStrcat(*buf, BAD_CAST " '");
680 *buf = xmlStrcat(*buf, elem->name);
681 *buf = xmlStrcat(*buf, BAD_CAST "'");
682 } else {
683 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
684 *buf = xmlStrcat(*buf, BAD_CAST " '");
685 *buf = xmlStrcat(*buf, elem->refPrefix);
686 *buf = xmlStrcat(*buf, BAD_CAST ":");
687 *buf = xmlStrcat(*buf, elem->ref);
688 *buf = xmlStrcat(*buf, BAD_CAST "'");
689 }
690 }
691 } else if (itemNode != NULL) {
692 xmlNodePtr elem;
693
694 if (itemNode->type == XML_ATTRIBUTE_NODE)
695 elem = itemNode->parent;
696 else
697 elem = itemNode;
698 *buf = xmlStrdup(BAD_CAST "Element '");
699 if (parsing)
700 *buf = xmlStrcat(*buf, elem->name);
701 else
702 *buf = xmlStrcat(*buf,
703 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
704 *buf = xmlStrcat(*buf, BAD_CAST "'");
705 }
706 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
707 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
708 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
709 itemNode->ns, itemNode->name));
710 *buf = xmlStrcat(*buf, BAD_CAST "'");
711 }
712 FREE_AND_NULL(str);
713
714 return (*buf);
715}
716
717/**
718 * xmlSchemaPFormatItemDes:
719 * @buf: the string buffer
720 * @item: the item as a schema object
721 * @itemNode: the item as a node
722 *
723 * If the pointer to @buf is not NULL and @but holds no value,
724 * the value is set to a item designation using
725 * xmlSchemaFormatItemForReport. This one avoids adding
726 * an attribute designation postfix.
727 *
728 * Returns a string of all enumeration elements.
729 */
730static void
731xmlSchemaPRequestItemDes(xmlChar **buf,
732 xmlSchemaTypePtr item,
733 xmlNodePtr itemNode)
734{
735 if ((buf == 0) || (*buf != NULL))
736 return;
737 if (itemNode->type == XML_ATTRIBUTE_NODE)
738 itemNode = itemNode->parent;
739 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
740}
741
742/**
743 * xmlSchemaFormatFacetEnumSet:
744 * @buf: the string buffer
745 * @type: the type holding the enumeration facets
746 *
747 * Builds a string consisting of all enumeration elements.
748 *
749 * Returns a string of all enumeration elements.
750 */
751static const xmlChar *
752xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
753{
754 xmlSchemaFacetLinkPtr link;
755
756 if (*buf != NULL)
757 xmlFree(*buf);
758 *buf = NULL;
759 for (link = type->facetSet; link != NULL; link = link->next) {
760 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
761 if (*buf == NULL) {
762 *buf = xmlStrdup(BAD_CAST "'");
763 *buf = xmlStrcat(*buf, link->facet->value);
764 *buf = xmlStrcat(*buf, BAD_CAST "'");
765 } else {
766 *buf = xmlStrcat(*buf, BAD_CAST ", '");
767 *buf = xmlStrcat(*buf, link->facet->value);
768 *buf = xmlStrcat(*buf, BAD_CAST "'");
769 }
770 }
771 }
772 return ((const xmlChar *) *buf);
773}
774
775/**
776 * xmlSchemaVFacetErr:
777 * @ctxt: the schema validation context
778 * @error: the error code
779 * @node: the node to be validated
780 * @value: the value of the node
781 * @type: the type holding the facet
782 * @facet: the facet
783 * @message: the error message of NULL
784 * @str1: extra data
785 * @str2: extra data
786 * @str3: extra data
787 *
788 * Reports a facet validation error.
789 * TODO: Should this report the value of an element as well?
790 */
791static void
792xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
793 xmlParserErrors error,
794 xmlNodePtr node,
795 const xmlChar *value,
796 unsigned long length,
797 xmlSchemaTypePtr type,
798 xmlSchemaFacetPtr facet,
799 const char *message,
800 const xmlChar *str1,
801 const xmlChar *str2,
802 const xmlChar *str3)
803{
804 xmlChar *str = NULL, *msg = NULL;
805 xmlSchemaTypeType facetType;
806
807 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
808 msg = xmlStrcat(msg, BAD_CAST " [");
809 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
810 msg = xmlStrcat(msg, BAD_CAST ", facet '");
811 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
812 facetType = XML_SCHEMA_FACET_ENUMERATION;
813 /*
814 * If enumerations are validated, one must not expect the
815 * facet to be given.
816 */
817 } else
818 facetType = facet->type;
819 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
820 msg = xmlStrcat(msg, BAD_CAST "']: ");
821 if (message == NULL) {
822 /*
823 * Use a default message.
824 */
825 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
826 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
827 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
828
829 char len[25], actLen[25];
830
831 /* FIXME, TODO: What is the max expected string length of the
832 * this value?
833 */
834 if (node->type == XML_ATTRIBUTE_NODE)
835 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
836 else
837 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
838
839 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
840 snprintf(actLen, 24, "%lu", length);
841
842 if (facetType == XML_SCHEMA_FACET_LENGTH)
843 msg = xmlStrcat(msg,
844 BAD_CAST "this differs from the allowed length of '%s'.\n");
845 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
846 msg = xmlStrcat(msg,
847 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
848 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
849 msg = xmlStrcat(msg,
850 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
851
852 if (node->type == XML_ATTRIBUTE_NODE)
853 xmlSchemaVErrExt(ctxt, node, error,
854 (const char *) msg,
855 value, (const xmlChar *) actLen, (const xmlChar *) len,
856 NULL, NULL);
857 else
858 xmlSchemaVErr(ctxt, node, error,
859 (const char *) msg,
860 (const xmlChar *) actLen, (const xmlChar *) len);
861
862 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
863 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
864 "of the set {%s}.\n");
865 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
866 xmlSchemaFormatFacetEnumSet(&str, type));
867 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
868 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
869 "by the pattern '%s'.\n");
870 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
871 facet->value);
872 } else if (node->type == XML_ATTRIBUTE_NODE) {
873 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
874 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
875 } else {
876 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
877 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
878 }
879 } else {
880 msg = xmlStrcat(msg, (const xmlChar *) message);
881 msg = xmlStrcat(msg, BAD_CAST ".\n");
882 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
883 }
884 FREE_AND_NULL(str)
885 xmlFree(msg);
886}
887
888/**
889 * xmlSchemaVSimpleTypeErr:
890 * @ctxt: the schema validation context
891 * @error: the error code
892 * @type: the type used for validation
893 * @node: the node containing the validated value
894 * @value: the validated value
895 *
896 * Reports a simple type validation error.
897 * TODO: Should this report the value of an element as well?
898 */
899static void
900xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
901 xmlParserErrors error,
902 xmlNodePtr node,
903 const xmlChar *value,
904 xmlSchemaTypePtr type)
905{
906 xmlChar *str = NULL, *msg = NULL;
907
908 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
909 msg = xmlStrcat(msg, BAD_CAST " [");
910 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
911 if (node->type == XML_ATTRIBUTE_NODE) {
912 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
913 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
914 } else {
915 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
916 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
917 }
918 FREE_AND_NULL(str)
919 xmlFree(msg);
920}
921
922/**
923 * xmlSchemaPMissingAttrErr:
924 * @ctxt: the schema validation context
925 * @ownerDes: the designation of the owner
926 * @ownerName: the name of the owner
927 * @ownerItem: the owner as a schema object
928 * @ownerElem: the owner as an element node
929 * @node: the parent element node of the missing attribute node
930 * @type: the corresponding type of the attribute node
931 *
932 * Reports an illegal attribute.
933 */
934static void
935xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
936 xmlParserErrors error,
937 xmlChar **ownerDes,
938 xmlSchemaTypePtr ownerItem,
939 xmlNodePtr ownerElem,
940 const char *name,
941 const char *message)
942{
943 xmlChar *des = NULL;
944
945 if (ownerDes == NULL)
946 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
947 else if (*ownerDes == NULL) {
948 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
949 des = *ownerDes;
950 } else
951 des = *ownerDes;
952 if (message != NULL)
953 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
954 else
955 xmlSchemaPErr(ctxt, ownerElem, error,
956 "%s: The attribute '%s' is required but missing.\n",
957 BAD_CAST des, BAD_CAST name);
958 if (ownerDes == NULL)
959 FREE_AND_NULL(des);
960}
961
962static const char *
963xmlSchemaCompTypeToString(xmlSchemaTypeType type)
964{
965 switch (type) {
966 case XML_SCHEMA_TYPE_SIMPLE:
967 return("simple type definition");
968 case XML_SCHEMA_TYPE_COMPLEX:
969 return("complex type definition");
970 case XML_SCHEMA_TYPE_ELEMENT:
971 return("element declaration");
972 case XML_SCHEMA_TYPE_ATTRIBUTE:
973 return("attribute declaration");
974 case XML_SCHEMA_TYPE_GROUP:
975 return("model group definition");
976 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
977 return("attribute group definition");
978 case XML_SCHEMA_TYPE_NOTATION:
979 return("notation declaration");
980 default:
981 return("Not a schema component");
982 }
983}
984/**
985 * xmlSchemaPResCompAttrErr:
986 * @ctxt: the schema validation context
987 * @error: the error code
988 * @ownerDes: the designation of the owner
989 * @ownerItem: the owner as a schema object
990 * @ownerElem: the owner as an element node
991 * @name: the name of the attribute holding the QName
992 * @refName: the referenced local name
993 * @refURI: the referenced namespace URI
994 * @message: optional message
995 *
996 * Used to report QName attribute values that failed to resolve
997 * to schema components.
998 */
999static void
1000xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1001 xmlParserErrors error,
1002 xmlChar **ownerDes,
1003 xmlSchemaTypePtr ownerItem,
1004 xmlNodePtr ownerElem,
1005 const char *name,
1006 const xmlChar *refName,
1007 const xmlChar *refURI,
1008 xmlSchemaTypeType refType,
1009 const char *refTypeStr)
1010{
1011 xmlChar *des = NULL, *strA = NULL;
1012
1013 if (ownerDes == NULL)
1014 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1015 else if (*ownerDes == NULL) {
1016 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1017 des = *ownerDes;
1018 } else
1019 des = *ownerDes;
1020 /*
1021 if (message != NULL)
1022 xmlSchemaPErrExt(ctxt, ownerElem, error, NULL, NULL, NULL,
1023 "%s, attribute '%s': %s.\n",
1024 BAD_CAST des, name, message, NULL, NULL);
1025 else
1026 */
1027 if (refTypeStr == NULL)
1028 refTypeStr = xmlSchemaCompTypeToString(refType);
1029 xmlSchemaPErrExt(ctxt, ownerElem, error,
1030 NULL, NULL, NULL,
1031 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1032 "%s.\n", BAD_CAST des, BAD_CAST name,
1033 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1034 BAD_CAST refTypeStr, NULL);
1035 if (ownerDes == NULL)
1036 FREE_AND_NULL(des)
1037 FREE_AND_NULL(strA)
1038}
1039
1040static void
1041xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
1042 xmlParserErrors error,
1043 xmlChar **ownerDes,
1044 xmlSchemaTypePtr ownerItem,
1045 xmlAttrPtr attr,
1046 const char *msg)
1047{
1048 xmlChar *des = NULL;
1049
1050 if (ownerDes == NULL)
1051 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1052 else if (*ownerDes == NULL) {
1053 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1054 des = *ownerDes;
1055 } else
1056 des = *ownerDes;
1057 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1058 "%s, attribute '%s': %s.\n",
1059 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1060 if (ownerDes == NULL)
1061 FREE_AND_NULL(des);
1062}
1063
1064/**
1065 * xmlSchemaPIllegalAttrErr:
1066 * @ctxt: the schema validation context
1067 * @error: the error code
1068 * @ownerDes: the designation of the owner
1069 * @ownerItem: the owner as a schema object
1070 * @attr: the illegal attribute node
1071 *
1072 * Reports an illegal attribute.
1073 */
1074static void
1075xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1076 xmlParserErrors error,
1077 xmlChar **ownerDes,
1078 xmlSchemaTypePtr ownerItem,
1079 xmlAttrPtr attr)
1080{
1081 xmlChar *des = NULL, *strA = NULL;
1082
1083 if (ownerDes == NULL)
1084 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1085 else if (*ownerDes == NULL) {
1086 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1087 des = *ownerDes;
1088 } else
1089 des = *ownerDes;
1090 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1091 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1092 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1093 if (ownerDes == NULL)
1094 FREE_AND_NULL(des);
1095 FREE_AND_NULL(strA);
1096}
1097
1098static void
1099xmlSchemaPAquireDes(xmlChar **des,
1100 xmlChar **itemDes,
1101 xmlSchemaTypePtr item,
1102 xmlNodePtr itemElem)
1103{
1104 if (itemDes == NULL)
1105 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1106 else if (*itemDes == NULL) {
1107 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1108 *des = *itemDes;
1109 } else
1110 *des = *itemDes;
1111}
1112
1113static void
1114xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1115 xmlParserErrors error,
1116 xmlChar **itemDes,
1117 xmlSchemaTypePtr item,
1118 xmlNodePtr itemElem,
1119 const char *message,
1120 const xmlChar *str1,
1121 const xmlChar *str2,
1122 const xmlChar *str3)
1123{
1124 xmlChar *des = NULL, *msg = NULL;
1125
1126 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1127 msg = xmlStrdup(BAD_CAST "%s: ");
1128 msg = xmlStrcat(msg, (const xmlChar *) message);
1129 msg = xmlStrcat(msg, BAD_CAST ".\n");
1130 if ((itemElem == NULL) && (item != NULL))
1131 itemElem = item->node;
1132 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1133 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1134 if (itemDes == NULL)
1135 FREE_AND_NULL(des);
1136 FREE_AND_NULL(msg);
1137}
1138
1139static void
1140xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1141 xmlParserErrors error,
1142 xmlChar **itemDes,
1143 xmlSchemaTypePtr item,
1144 xmlNodePtr itemElem,
1145 const char *message,
1146 const xmlChar *str1)
1147{
1148 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1149 str1, NULL, NULL);
1150}
1151
1152static void
1153xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1154 xmlParserErrors error,
1155 xmlChar **itemDes,
1156 xmlSchemaTypePtr item,
1157 xmlNodePtr itemElem,
1158 const xmlSchemaAttributePtr attr,
1159 const char *message,
1160 const xmlChar *str1)
1161{
1162 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1163
1164 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1165 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1166 xmlSchemaGetAttrName(attr));
1167 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1168 msg = xmlStrcat(msg, (const xmlChar *) message);
1169 msg = xmlStrcat(msg, BAD_CAST ".\n");
1170 if ((itemElem == NULL) && (item != NULL))
1171 itemElem = item->node;
1172 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1173 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1174 if (itemDes == NULL)
1175 FREE_AND_NULL(des);
1176 FREE_AND_NULL(strA);
1177 xmlFree(msg);
1178}
1179
1180
1181
1182static void
1183xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1184 xmlParserErrors error,
1185 xmlChar **itemDes,
1186 xmlSchemaTypePtr item,
1187 xmlSchemaTypePtr baseItem,
1188 xmlSchemaFacetPtr facet)
1189{
1190 xmlChar *des = NULL, *strT = NULL;
1191
1192 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1193 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1194 "%s: The facet '%s' is not allowed on types derived from the "
1195 "type %s.\n",
1196 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1197 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1198 NULL, NULL);
1199 if (itemDes == NULL)
1200 FREE_AND_NULL(des);
1201 FREE_AND_NULL(strT);
1202}
1203
1204static void
1205xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1206 xmlParserErrors error,
1207 xmlChar **itemDes,
1208 xmlSchemaTypePtr item,
1209 xmlSchemaFacetPtr facet)
1210{
1211 xmlChar *des = NULL, *strT = NULL;
1212
1213 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1214 xmlSchemaPErr(ctxt, item->node, error,
1215 "%s: The facet '%s' is not allowed.\n",
1216 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1217 if (itemDes == NULL)
1218 FREE_AND_NULL(des);
1219 FREE_AND_NULL(strT);
1220}
1221
1222/**
1223 * xmlSchemaPMutualExclAttrErr:
1224 * @ctxt: the schema validation context
1225 * @error: the error code
1226 * @elemDes: the designation of the parent element node
1227 * @attr: the bad attribute node
1228 * @type: the corresponding type of the attribute node
1229 *
1230 * Reports an illegal attribute.
1231 */
1232static void
1233xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1234 xmlParserErrors error,
1235 xmlChar **ownerDes,
1236 xmlSchemaTypePtr ownerItem,
1237 xmlAttrPtr attr,
1238 const char *name1,
1239 const char *name2)
1240{
1241 xmlChar *des = NULL;
1242
1243 if (ownerDes == NULL)
1244 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1245 else if (*ownerDes == NULL) {
1246 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1247 des = *ownerDes;
1248 } else
1249 des = *ownerDes;
1250 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1251 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1252 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1253 if (ownerDes == NULL)
1254 FREE_AND_NULL(des)
1255}
1256
1257/**
1258 * xmlSchemaPSimpleTypeErr:
1259 * @ctxt: the schema validation context
1260 * @error: the error code
1261 * @biType: the built in type specifier
1262 * @ownerDes: the designation of the owner
1263 * @ownerItem: the schema object if existent
1264 * @node: the validated node
1265 * @value: the validated value
1266 *
1267 * Reports a simple type validation error.
1268 * TODO: Should this report the value of an element as well?
1269 */
1270static void
1271xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1272 xmlParserErrors error,
1273 xmlChar **ownerDes,
1274 xmlSchemaTypePtr ownerItem,
1275 xmlNodePtr node,
1276 xmlSchemaValType biType,
1277 const char *typeDes,
1278 const xmlChar *value,
1279 const char *message,
1280 const xmlChar *str1,
1281 const xmlChar *str2)
1282{
1283 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
1284 xmlSchemaTypePtr type = NULL;
1285
1286 if (ownerDes == NULL)
1287 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1288 else if (*ownerDes == NULL) {
1289 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1290 des = *ownerDes;
1291 } else
1292 des = *ownerDes;
1293 if (biType != XML_SCHEMAS_UNKNOWN) {
1294 type = xmlSchemaGetBuiltInType(biType);
1295 if (type == NULL) {
1296 xmlSchemaPErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
1297 "Internal error: xmlSchemaPSimpleTypeErr, could not "
1298 "aquire the built-in type.\n",
1299 BAD_CAST des, BAD_CAST typeDes);
1300 return;
1301 }
1302 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
1303 }
1304 if (message == NULL) {
1305 /*
1306 * Use default messages.
1307 */
1308 if (node->type == XML_ATTRIBUTE_NODE) {
1309 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1310 "%s, attribute '%s' [%s]: The value '%s' is not "
1311 "valid.\n",
1312 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1313 node->name), BAD_CAST typeDes, value, NULL);
1314 } else {
1315 xmlSchemaPErr(ctxt, node, error,
1316 "%s [%s]: The character content is not valid.\n",
1317 BAD_CAST des, BAD_CAST typeDes);
1318 }
1319 } else {
1320 xmlChar *msg;
1321
1322 msg = xmlStrdup(BAD_CAST "%s");
1323 if (node->type == XML_ATTRIBUTE_NODE)
1324 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1325 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1326 msg = xmlStrcat(msg, (const xmlChar *) message);
1327 msg = xmlStrcat(msg, BAD_CAST ".\n");
1328 if (node->type == XML_ATTRIBUTE_NODE) {
1329 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1330 (const char *) msg,
1331 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1332 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1333 } else {
1334 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1335 (const char *) msg,
1336 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1337 }
1338 xmlFree(msg);
1339 }
1340 /* Cleanup. */
1341 FREE_AND_NULL(strA)
1342 FREE_AND_NULL(strT)
1343 if (ownerDes == NULL)
1344 FREE_AND_NULL(des)
1345}
1346
1347static void
1348xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1349 xmlParserErrors error,
1350 xmlChar **ownerDes,
1351 xmlSchemaTypePtr ownerItem,
1352 xmlNodePtr ownerElem,
1353 xmlNodePtr child,
1354 const char *message,
1355 const char *content)
1356{
1357 xmlChar *des = NULL;
1358
1359 if (ownerDes == NULL)
1360 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1361 else if (*ownerDes == NULL) {
1362 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1363 des = *ownerDes;
1364 } else
1365 des = *ownerDes;
1366 if (message != NULL)
1367 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1368 "%s: %s.\n",
1369 BAD_CAST des, BAD_CAST message);
1370 else {
1371 if (content != NULL) {
1372 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1373 "%s: The content is not valid. Expected is %s.\n",
1374 BAD_CAST des, BAD_CAST content);
1375 } else {
1376 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1377 "%s: The content is not valid.\n",
1378 BAD_CAST des, NULL);
1379 }
1380 }
1381 if (ownerDes == NULL)
1382 FREE_AND_NULL(des)
1383}
1384
1385/**
1386 * xmlSchemaVIllegalAttrErr:
1387 * @ctxt: the schema validation context
1388 * @attr: the illegal attribute node
1389 *
1390 * Reports an illegal attribute.
1391 */
1392static void
1393xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
1394 xmlAttrPtr attr)
1395{
1396 xmlChar *strE = NULL, *strA = NULL;
1397
1398 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1399 XML_SCHEMAS_ERR_ATTRUNKNOWN,
1400 "%s: The attribute '%s' is not allowed.\n",
1401 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1402 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1403 FREE_AND_NULL(strE)
1404 FREE_AND_NULL(strA)
1405}
1406
1407static void
1408xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1409 xmlParserErrors error,
1410 xmlNodePtr node,
1411 const char *message,
1412 const xmlChar *str1)
1413{
1414 xmlChar *des = NULL, *msg = NULL;
1415
1416 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1417 msg = xmlStrdup(BAD_CAST "%s: ");
1418 msg = xmlStrcat(msg, (const xmlChar *) message);
1419 msg = xmlStrcat(msg, BAD_CAST ".\n");
1420 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg,
1421 BAD_CAST des, str1, NULL, NULL, NULL);
1422 FREE_AND_NULL(des);
1423 FREE_AND_NULL(msg);
1424}
1425
1426static const char *
1427xmlSchemaWildcardPCToString(int pc)
1428{
1429 switch (pc) {
1430 case XML_SCHEMAS_ANY_SKIP:
1431 return ("skip");
1432 case XML_SCHEMAS_ANY_LAX:
1433 return ("lax");
1434 case XML_SCHEMAS_ANY_STRICT:
1435 return ("strict");
1436 default:
1437 return ("invalid process contents");
1438 }
1439}
1440
1441static void
1442xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1443 xmlParserErrors error,
1444 xmlNodePtr node,
1445 xmlSchemaWildcardPtr wild,
1446 const char *message)
1447{
1448 xmlChar *des = NULL, *msg = NULL;
1449
1450 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1451 msg = xmlStrdup(BAD_CAST "%s, [");
1452 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1453 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1454 msg = xmlStrcat(msg, (const xmlChar *) message);
1455 msg = xmlStrcat(msg, BAD_CAST ".\n");
1456 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1457 FREE_AND_NULL(des);
1458 FREE_AND_NULL(msg);
1459}
1460
1461/**
1462 * xmlSchemaVMissingAttrErr:
1463 * @ctxt: the schema validation context
1464 * @node: the parent element node of the missing attribute node
1465 * @type: the corresponding type of the attribute node
1466 *
1467 * Reports an illegal attribute.
1468 */
1469static void
1470xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1471 xmlNodePtr elem,
1472 xmlSchemaAttributePtr type)
1473{
1474 const xmlChar *name, *uri;
1475 xmlChar *strE = NULL, *strA = NULL;
1476
1477 if (type->ref != NULL) {
1478 name = type->ref;
1479 uri = type->refNs;
1480 } else {
1481 name = type->name;
1482 uri = type->targetNamespace;
1483 }
1484 xmlSchemaVErr(ctxt, elem,
1485 XML_SCHEMAS_ERR_MISSING,
1486 "%s: The attribute %s is required but missing.\n",
1487 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1488 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1489 FREE_AND_NULL(strE)
1490 FREE_AND_NULL(strA)
1491}
1492
Daniel Veillard4255d502002-04-16 15:50:10 +00001493/************************************************************************
1494 * *
1495 * Allocation functions *
1496 * *
1497 ************************************************************************/
1498
1499/**
1500 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +00001501 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001502 *
1503 * Allocate a new Schema structure.
1504 *
1505 * Returns the newly allocated structure or NULL in case or error
1506 */
1507static xmlSchemaPtr
1508xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1509{
1510 xmlSchemaPtr ret;
1511
1512 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1513 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001514 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001515 return (NULL);
1516 }
1517 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001518 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001519 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001520
1521 return (ret);
1522}
1523
1524/**
1525 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001526 *
1527 * Allocate a new Facet structure.
1528 *
1529 * Returns the newly allocated structure or NULL in case or error
1530 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001531xmlSchemaFacetPtr
1532xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001533{
1534 xmlSchemaFacetPtr ret;
1535
1536 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1537 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001538 return (NULL);
1539 }
1540 memset(ret, 0, sizeof(xmlSchemaFacet));
1541
1542 return (ret);
1543}
1544
1545/**
1546 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001547 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001548 * @node: a node
1549 *
1550 * Allocate a new annotation structure.
1551 *
1552 * Returns the newly allocated structure or NULL in case or error
1553 */
1554static xmlSchemaAnnotPtr
1555xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1556{
1557 xmlSchemaAnnotPtr ret;
1558
1559 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1560 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001561 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001562 return (NULL);
1563 }
1564 memset(ret, 0, sizeof(xmlSchemaAnnot));
1565 ret->content = node;
1566 return (ret);
1567}
1568
1569/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001570 * xmlSchemaFreeAnnot:
1571 * @annot: a schema type structure
1572 *
1573 * Deallocate a annotation structure
1574 */
1575static void
1576xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1577{
1578 if (annot == NULL)
1579 return;
1580 xmlFree(annot);
1581}
1582
1583/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001584 * xmlSchemaFreeImport:
1585 * @import: a schema import structure
1586 *
1587 * Deallocate an import structure
1588 */
1589static void
1590xmlSchemaFreeImport(xmlSchemaImportPtr import)
1591{
1592 if (import == NULL)
1593 return;
1594
1595 xmlSchemaFree(import->schema);
Daniel Veillard1d913862003-11-21 00:28:39 +00001596 xmlFree(import);
1597}
1598
1599/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001600 * xmlSchemaFreeInclude:
1601 * @include: a schema include structure
1602 *
1603 * Deallocate an include structure
1604 */
1605static void
1606xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1607{
1608 if (include == NULL)
1609 return;
1610
1611 xmlFreeDoc(include->doc);
1612 xmlFree(include);
1613}
1614
1615/**
1616 * xmlSchemaFreeIncludeList:
1617 * @includes: a schema include list
1618 *
1619 * Deallocate an include structure
1620 */
1621static void
1622xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1623{
1624 xmlSchemaIncludePtr next;
1625
1626 while (includes != NULL) {
1627 next = includes->next;
1628 xmlSchemaFreeInclude(includes);
1629 includes = next;
1630 }
1631}
1632
1633/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001634 * xmlSchemaFreeNotation:
1635 * @schema: a schema notation structure
1636 *
1637 * Deallocate a Schema Notation structure.
1638 */
1639static void
1640xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1641{
1642 if (nota == NULL)
1643 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001644 xmlFree(nota);
1645}
1646
1647/**
1648 * xmlSchemaFreeAttribute:
1649 * @schema: a schema attribute structure
1650 *
1651 * Deallocate a Schema Attribute structure.
1652 */
1653static void
1654xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1655{
1656 if (attr == NULL)
1657 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001658 if (attr->annot != NULL)
1659 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001660 xmlFree(attr);
1661}
1662
1663/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001664 * xmlSchemaFreeWildcardNsSet:
1665 * set: a schema wildcard namespace
1666 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001667 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001668 */
1669static void
1670xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1671{
1672 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001673
Daniel Veillard3646d642004-06-02 19:19:14 +00001674 while (set != NULL) {
1675 next = set->next;
1676 xmlFree(set);
1677 set = next;
1678 }
1679}
1680
1681/**
1682 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001683 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001684 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001685 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001686 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001687void
Daniel Veillard3646d642004-06-02 19:19:14 +00001688xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
1689{
1690 if (wildcard == NULL)
1691 return;
1692 if (wildcard->annot != NULL)
1693 xmlSchemaFreeAnnot(wildcard->annot);
1694 if (wildcard->nsSet != NULL)
1695 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
1696 if (wildcard->negNsSet != NULL)
1697 xmlFree(wildcard->negNsSet);
1698 xmlFree(wildcard);
1699}
1700
1701/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001702 * xmlSchemaFreeAttributeGroup:
1703 * @schema: a schema attribute group structure
1704 *
1705 * Deallocate a Schema Attribute Group structure.
1706 */
1707static void
1708xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
1709{
1710 if (attr == NULL)
1711 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00001712 if (attr->annot != NULL)
1713 xmlSchemaFreeAnnot(attr->annot);
1714 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
1715 (attr->attributeWildcard != NULL))
1716 xmlSchemaFreeWildcard(attr->attributeWildcard);
1717
Daniel Veillard4255d502002-04-16 15:50:10 +00001718 xmlFree(attr);
1719}
1720
1721/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001722 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001723 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00001724 *
1725 * Deallocate a list of schema attribute uses.
1726 */
1727static void
1728xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
1729{
1730 xmlSchemaAttributeLinkPtr next;
1731
1732 while (attrUse != NULL) {
1733 next = attrUse->next;
1734 xmlFree(attrUse);
1735 attrUse = next;
1736 }
1737}
1738
1739/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00001740 * xmlSchemaFreeTypeLinkList:
1741 * @alink: a type link
1742 *
1743 * Deallocate a list of types.
1744 */
1745static void
1746xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
1747{
1748 xmlSchemaTypeLinkPtr next;
1749
1750 while (link != NULL) {
1751 next = link->next;
1752 xmlFree(link);
1753 link = next;
1754 }
1755}
1756
1757/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001758 * xmlSchemaFreeElement:
1759 * @schema: a schema element structure
1760 *
1761 * Deallocate a Schema Element structure.
1762 */
1763static void
1764xmlSchemaFreeElement(xmlSchemaElementPtr elem)
1765{
1766 if (elem == NULL)
1767 return;
Daniel Veillard32370232002-10-16 14:08:14 +00001768 if (elem->annot != NULL)
1769 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001770 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001771 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00001772 xmlFree(elem);
1773}
1774
1775/**
1776 * xmlSchemaFreeFacet:
1777 * @facet: a schema facet structure
1778 *
1779 * Deallocate a Schema Facet structure.
1780 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001781void
Daniel Veillard4255d502002-04-16 15:50:10 +00001782xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
1783{
1784 if (facet == NULL)
1785 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001786 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001787 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00001788 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001789 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00001790 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001791 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001792 xmlFree(facet);
1793}
1794
1795/**
1796 * xmlSchemaFreeType:
1797 * @type: a schema type structure
1798 *
1799 * Deallocate a Schema Type structure.
1800 */
1801void
1802xmlSchemaFreeType(xmlSchemaTypePtr type)
1803{
1804 if (type == NULL)
1805 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001806 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00001807 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001808 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001809 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00001810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001811 facet = type->facets;
1812 while (facet != NULL) {
1813 next = facet->next;
1814 xmlSchemaFreeFacet(facet);
1815 facet = next;
1816 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001817 }
Daniel Veillard3646d642004-06-02 19:19:14 +00001818 if (type->type != XML_SCHEMA_TYPE_BASIC) {
1819 if (type->attributeUses != NULL)
1820 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard01fa6152004-06-29 17:04:39 +00001821 /* TODO: There must be a way more simple than this. */
Daniel Veillard3646d642004-06-02 19:19:14 +00001822 if ((type->attributeWildcard != NULL) &&
1823 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
1824 ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
1825 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)))) {
1826 xmlSchemaFreeWildcard(type->attributeWildcard);
1827 }
1828 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00001829 if (type->memberTypes != NULL)
1830 xmlSchemaFreeTypeLinkList(type->memberTypes);
1831 if (type->facetSet != NULL) {
1832 xmlSchemaFacetLinkPtr next, link;
1833
1834 link = type->facetSet;
1835 do {
1836 next = link->next;
1837 xmlFree(link);
1838 link = next;
1839 } while (link != NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00001840 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001841 xmlFree(type);
1842}
1843
1844/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001845 * xmlSchemaFreeTypeList:
1846 * @type: a schema type structure
1847 *
1848 * Deallocate a Schema Type structure.
1849 */
1850static void
1851xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
1852{
1853 xmlSchemaTypePtr next;
1854
1855 while (type != NULL) {
1856 next = type->redef;
1857 xmlSchemaFreeType(type);
1858 type = next;
1859 }
1860}
1861
1862/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001863 * xmlSchemaFree:
1864 * @schema: a schema structure
1865 *
1866 * Deallocate a Schema structure.
1867 */
1868void
1869xmlSchemaFree(xmlSchemaPtr schema)
1870{
1871 if (schema == NULL)
1872 return;
1873
Daniel Veillard4255d502002-04-16 15:50:10 +00001874 if (schema->notaDecl != NULL)
1875 xmlHashFree(schema->notaDecl,
1876 (xmlHashDeallocator) xmlSchemaFreeNotation);
1877 if (schema->attrDecl != NULL)
1878 xmlHashFree(schema->attrDecl,
1879 (xmlHashDeallocator) xmlSchemaFreeAttribute);
1880 if (schema->attrgrpDecl != NULL)
1881 xmlHashFree(schema->attrgrpDecl,
1882 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
1883 if (schema->elemDecl != NULL)
1884 xmlHashFree(schema->elemDecl,
1885 (xmlHashDeallocator) xmlSchemaFreeElement);
1886 if (schema->typeDecl != NULL)
1887 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00001888 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00001889 if (schema->groupDecl != NULL)
1890 xmlHashFree(schema->groupDecl,
1891 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00001892 if (schema->schemasImports != NULL)
1893 xmlHashFree(schema->schemasImports,
1894 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001895 if (schema->includes != NULL) {
1896 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
1897 }
Daniel Veillard4255d502002-04-16 15:50:10 +00001898 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001899 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00001900 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001901 xmlFreeDoc(schema->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001902 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001903
1904 xmlFree(schema);
1905}
1906
1907/************************************************************************
1908 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00001909 * Debug functions *
1910 * *
1911 ************************************************************************/
1912
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001913#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001914
Daniel Veillard4255d502002-04-16 15:50:10 +00001915/**
1916 * xmlSchemaElementDump:
1917 * @elem: an element
1918 * @output: the file output
1919 *
1920 * Dump the element
1921 */
1922static void
1923xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001924 const xmlChar * name ATTRIBUTE_UNUSED,
1925 const xmlChar * context ATTRIBUTE_UNUSED,
1926 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00001927{
1928 if (elem == NULL)
1929 return;
1930
1931 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00001932 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
1933 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00001934 fprintf(output, ": %s ", elem->name);
1935 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001936 fprintf(output, "namespace '%s' ", namespace);
1937
Daniel Veillard4255d502002-04-16 15:50:10 +00001938 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001939 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00001940 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001941 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00001942 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001943 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00001944 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001945 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00001946 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001947 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00001948 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001949 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00001950 fprintf(output, "\n");
1951 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001952 fprintf(output, " ");
1953 if (elem->minOccurs != 1)
1954 fprintf(output, "min: %d ", elem->minOccurs);
1955 if (elem->maxOccurs >= UNBOUNDED)
1956 fprintf(output, "max: unbounded\n");
1957 else if (elem->maxOccurs != 1)
1958 fprintf(output, "max: %d\n", elem->maxOccurs);
1959 else
1960 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001961 }
1962 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001963 fprintf(output, " type: %s", elem->namedType);
1964 if (elem->namedTypeNs != NULL)
1965 fprintf(output, " ns %s\n", elem->namedTypeNs);
1966 else
1967 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001968 }
1969 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001970 fprintf(output, " substitutionGroup: %s", elem->substGroup);
1971 if (elem->substGroupNs != NULL)
1972 fprintf(output, " ns %s\n", elem->substGroupNs);
1973 else
1974 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00001975 }
1976 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001977 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00001978}
1979
1980/**
1981 * xmlSchemaAnnotDump:
1982 * @output: the file output
1983 * @annot: a annotation
1984 *
1985 * Dump the annotation
1986 */
1987static void
1988xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
1989{
1990 xmlChar *content;
1991
1992 if (annot == NULL)
1993 return;
1994
1995 content = xmlNodeGetContent(annot->content);
1996 if (content != NULL) {
1997 fprintf(output, " Annot: %s\n", content);
1998 xmlFree(content);
1999 } else
2000 fprintf(output, " Annot: empty\n");
2001}
2002
2003/**
2004 * xmlSchemaTypeDump:
2005 * @output: the file output
2006 * @type: a type structure
2007 *
2008 * Dump a SchemaType structure
2009 */
2010static void
2011xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2012{
2013 if (type == NULL) {
2014 fprintf(output, "Type: NULL\n");
2015 return;
2016 }
2017 fprintf(output, "Type: ");
2018 if (type->name != NULL)
2019 fprintf(output, "%s, ", type->name);
2020 else
2021 fprintf(output, "no name");
2022 switch (type->type) {
2023 case XML_SCHEMA_TYPE_BASIC:
2024 fprintf(output, "basic ");
2025 break;
2026 case XML_SCHEMA_TYPE_SIMPLE:
2027 fprintf(output, "simple ");
2028 break;
2029 case XML_SCHEMA_TYPE_COMPLEX:
2030 fprintf(output, "complex ");
2031 break;
2032 case XML_SCHEMA_TYPE_SEQUENCE:
2033 fprintf(output, "sequence ");
2034 break;
2035 case XML_SCHEMA_TYPE_CHOICE:
2036 fprintf(output, "choice ");
2037 break;
2038 case XML_SCHEMA_TYPE_ALL:
2039 fprintf(output, "all ");
2040 break;
2041 case XML_SCHEMA_TYPE_UR:
2042 fprintf(output, "ur ");
2043 break;
2044 case XML_SCHEMA_TYPE_RESTRICTION:
2045 fprintf(output, "restriction ");
2046 break;
2047 case XML_SCHEMA_TYPE_EXTENSION:
2048 fprintf(output, "extension ");
2049 break;
2050 default:
2051 fprintf(output, "unknowntype%d ", type->type);
2052 break;
2053 }
2054 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002055 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002056 }
2057 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002058 case XML_SCHEMA_CONTENT_UNKNOWN:
2059 fprintf(output, "unknown ");
2060 break;
2061 case XML_SCHEMA_CONTENT_EMPTY:
2062 fprintf(output, "empty ");
2063 break;
2064 case XML_SCHEMA_CONTENT_ELEMENTS:
2065 fprintf(output, "element ");
2066 break;
2067 case XML_SCHEMA_CONTENT_MIXED:
2068 fprintf(output, "mixed ");
2069 break;
2070 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002071 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002072 break;
2073 case XML_SCHEMA_CONTENT_BASIC:
2074 fprintf(output, "basic ");
2075 break;
2076 case XML_SCHEMA_CONTENT_SIMPLE:
2077 fprintf(output, "simple ");
2078 break;
2079 case XML_SCHEMA_CONTENT_ANY:
2080 fprintf(output, "any ");
2081 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002082 }
2083 fprintf(output, "\n");
2084 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002085 fprintf(output, " ");
2086 if (type->minOccurs != 1)
2087 fprintf(output, "min: %d ", type->minOccurs);
2088 if (type->maxOccurs >= UNBOUNDED)
2089 fprintf(output, "max: unbounded\n");
2090 else if (type->maxOccurs != 1)
2091 fprintf(output, "max: %d\n", type->maxOccurs);
2092 else
2093 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002094 }
2095 if (type->annot != NULL)
2096 xmlSchemaAnnotDump(output, type->annot);
2097 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002098 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002099
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002100 fprintf(output, " subtypes: ");
2101 while (sub != NULL) {
2102 fprintf(output, "%s ", sub->name);
2103 sub = sub->next;
2104 }
2105 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002106 }
2107
2108}
2109
2110/**
2111 * xmlSchemaDump:
2112 * @output: the file output
2113 * @schema: a schema structure
2114 *
2115 * Dump a Schema structure.
2116 */
2117void
2118xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2119{
2120 if (schema == NULL) {
2121 fprintf(output, "Schemas: NULL\n");
2122 return;
2123 }
2124 fprintf(output, "Schemas: ");
2125 if (schema->name != NULL)
2126 fprintf(output, "%s, ", schema->name);
2127 else
2128 fprintf(output, "no name, ");
2129 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002130 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002131 else
2132 fprintf(output, "no target namespace");
2133 fprintf(output, "\n");
2134 if (schema->annot != NULL)
2135 xmlSchemaAnnotDump(output, schema->annot);
2136
2137 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2138 output);
2139 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002140 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002141}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002142#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002143
2144/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002145 * *
2146 * Utilities *
2147 * *
2148 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002149
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150/**
2151 * xmlSchemaGetPropNode:
2152 * @node: the element node
2153 * @name: the name of the attribute
2154 *
2155 * Seeks an attribute with a name of @name in
2156 * no namespace.
2157 *
2158 * Returns the attribute or NULL if not present.
2159 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002160static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002162{
2163 xmlAttrPtr prop;
2164
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 if ((node == NULL) || (name == NULL))
2166 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002167 prop = node->properties;
2168 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002169 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2170 return(prop);
2171 prop = prop->next;
2172 }
2173 return (NULL);
2174}
2175
2176/**
2177 * xmlSchemaGetPropNodeNs:
2178 * @node: the element node
2179 * @uri: the uri
2180 * @name: the name of the attribute
2181 *
2182 * Seeks an attribute with a local name of @name and
2183 * a namespace URI of @uri.
2184 *
2185 * Returns the attribute or NULL if not present.
2186 */
2187static xmlAttrPtr
2188xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2189{
2190 xmlAttrPtr prop;
2191
2192 if ((node == NULL) || (name == NULL))
2193 return(NULL);
2194 prop = node->properties;
2195 while (prop != NULL) {
2196 if ((prop->ns != NULL) &&
2197 xmlStrEqual(prop->name, BAD_CAST name) &&
2198 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002199 return(prop);
2200 prop = prop->next;
2201 }
2202 return (NULL);
2203}
2204
2205static const xmlChar *
2206xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2207{
2208 xmlChar *val;
2209 const xmlChar *ret;
2210
2211 val = xmlNodeGetContent(node);
2212 if (val == NULL)
2213 return(NULL);
2214 ret = xmlDictLookup(ctxt->dict, val, -1);
2215 xmlFree(val);
2216 return(ret);
2217}
2218
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002219/**
2220 * xmlSchemaGetProp:
2221 * @ctxt: the parser context
2222 * @node: the node
2223 * @name: the property name
2224 *
2225 * Read a attribute value and internalize the string
2226 *
2227 * Returns the string or NULL if not present.
2228 */
2229static const xmlChar *
2230xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2231 const char *name)
2232{
2233 xmlChar *val;
2234 const xmlChar *ret;
2235
2236 val = xmlGetProp(node, BAD_CAST name);
2237 if (val == NULL)
2238 return(NULL);
2239 ret = xmlDictLookup(ctxt->dict, val, -1);
2240 xmlFree(val);
2241 return(ret);
2242}
2243
William M. Brack29aa7722004-05-12 00:27:56 +00002244#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002245/**
2246 * xmlSchemaGetNamespace:
2247 * @ctxt: the parser context
2248 * @schema: the schemas containing the declaration
2249 * @node: the node
2250 * @qname: the QName to analyze
2251 *
2252 * Find the namespace name for the given declaration.
2253 *
2254 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00002255 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002256 */
2257static const xmlChar *
2258xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2259 xmlNodePtr node, const xmlChar *qname,
2260 const xmlChar **namespace) {
2261 int len;
2262 const xmlChar *name, *prefix, *def = NULL;
2263 xmlNsPtr ns;
2264
2265 *namespace = NULL;
2266
William M. Bracke7091952004-05-11 15:09:58 +00002267 /* TODO: The following seems to be not correct here:
2268 * 1. The name of a declaration is a NCName, not a QName.
2269 * 2. The attribute "targetNamespace" is allowed for the
2270 * <schema> Element Information Item only.
2271 * 3. One cannot evaluate the target namespace, by the type
2272 * of declaration, since it is dependant on the xxxFormDefault
2273 * of <schema> and the form attribute of an <element> or <attribute>.
2274 */
2275
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002276 if (xmlStrEqual(node->name, BAD_CAST "element") ||
2277 xmlStrEqual(node->name, BAD_CAST "attribute") ||
2278 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
2279 xmlStrEqual(node->name, BAD_CAST "complexType")) {
2280 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
2281 }
2282
William M. Bracke7091952004-05-11 15:09:58 +00002283
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002284 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
2285 name = xmlSplitQName3(qname, &len);
2286 if (name == NULL) {
2287 if (def == NULL) {
2288 if (xmlStrEqual(node->name, BAD_CAST "element")) {
2289 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
2290 *namespace = schema->targetNamespace;
2291 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
2292 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
2293 *namespace = schema->targetNamespace;
2294 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
2295 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
2296 *namespace = schema->targetNamespace;
2297 }
2298 } else {
2299 *namespace = def;
2300 }
2301 return(qname);
2302 }
William M. Bracke7091952004-05-11 15:09:58 +00002303
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002304 name = xmlDictLookup(ctxt->dict, name, -1);
2305 prefix = xmlDictLookup(ctxt->dict, qname, len);
2306 if (def != NULL) {
2307 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
2308 "%s: presence of both prefix %s and targetNamespace\n",
2309 node->name, prefix);
2310 }
2311 ns = xmlSearchNs(node->doc, node, prefix);
2312 if (ns == NULL) {
2313 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314 "%s: The QName prefix %s is undefined\n",
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002315 node->name, prefix);
2316 return(name);
2317 }
2318 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2319 return(name);
2320}
William M. Brack29aa7722004-05-12 00:27:56 +00002321#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002322
2323/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002324 * *
2325 * Parsing functions *
2326 * *
2327 ************************************************************************/
2328
2329/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002330 * xmlSchemaGetElem:
2331 * @schema: the schemas context
2332 * @name: the element name
2333 * @ns: the element namespace
Daniel Veillardf2a12832003-11-24 13:04:35 +00002334 * @level: how deep is the request
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002335 *
2336 * Lookup a an element in the schemas or the accessible schemas
2337 *
2338 * Returns the element definition or NULL if not found.
2339 */
2340static xmlSchemaElementPtr
2341xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardf2a12832003-11-24 13:04:35 +00002342 const xmlChar * namespace, int level)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002343{
2344 xmlSchemaElementPtr ret;
Daniel Veillardf2a12832003-11-24 13:04:35 +00002345 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002346
2347 if ((name == NULL) || (schema == NULL))
2348 return (NULL);
2349
Daniel Veillard3646d642004-06-02 19:19:14 +00002350
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002351 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002352 if ((ret != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002353 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_GLOBAL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002354 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002355 } else
2356 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002357 /*
2358 * This one was removed, since top level element declarations have
2359 * the target namespace specified in targetNamespace of the <schema>
2360 * information element, even if elementFormDefault is "unqualified".
2361 */
2362
2363 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002364 if (xmlStrEqual(namespace, schema->targetNamespace))
2365 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2366 else
2367 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002368 if ((ret != NULL) &&
2369 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002370 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002371 }
William M. Bracke7091952004-05-11 15:09:58 +00002372 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002373
2374 /* if (level > 0) */
2375 if (namespace == NULL)
2376 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
2377 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002378 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002379 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002380 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002381 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2382 return (ret);
2383 } else
2384 ret = NULL;
2385 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002386#ifdef DEBUG
2387 if (ret == NULL) {
2388 if (namespace == NULL)
2389 fprintf(stderr, "Unable to lookup type %s", name);
2390 else
2391 fprintf(stderr, "Unable to lookup type %s:%s", name,
2392 namespace);
2393 }
2394#endif
2395 return (ret);
2396}
2397
2398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002399 * xmlSchemaGetType:
2400 * @schema: the schemas context
2401 * @name: the type name
2402 * @ns: the type namespace
2403 *
2404 * Lookup a type in the schemas or the predefined types
2405 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002406 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 */
2408static xmlSchemaTypePtr
2409xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002410 const xmlChar * namespace)
2411{
Daniel Veillard4255d502002-04-16 15:50:10 +00002412 xmlSchemaTypePtr ret;
Daniel Veillard1d913862003-11-21 00:28:39 +00002413 xmlSchemaImportPtr import;
Daniel Veillard4255d502002-04-16 15:50:10 +00002414
2415 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002416 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002417 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002418 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002419 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002421 }
2422 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002423 if (ret != NULL)
2424 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002425 if (namespace == NULL)
2426 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
2427 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002428 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002429 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002430 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002431 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2432 return (ret);
2433 } else
2434 ret = NULL;
2435 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002436#ifdef DEBUG
2437 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002438 if (namespace == NULL)
2439 fprintf(stderr, "Unable to lookup type %s", name);
2440 else
2441 fprintf(stderr, "Unable to lookup type %s:%s", name,
2442 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002443 }
2444#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002445 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002446}
2447
Daniel Veillard3646d642004-06-02 19:19:14 +00002448/**
2449 * xmlSchemaGetAttribute:
2450 * @schema: the context of the schema
2451 * @name: the name of the attribute
2452 * @ns: the target namespace of the attribute
2453 *
2454 * Lookup a an attribute in the schema or imported schemas
2455 *
2456 * Returns the attribute declaration or NULL if not found.
2457 */
2458static xmlSchemaAttributePtr
2459xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2460 const xmlChar * namespace)
2461{
2462 xmlSchemaAttributePtr ret;
2463 xmlSchemaImportPtr import = NULL;
2464
2465 if ((name == NULL) || (schema == NULL))
2466 return (NULL);
2467
2468
2469 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2470 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2471 return (ret);
2472 else
2473 ret = NULL;
2474 if (namespace == NULL)
2475 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
2476 else
2477 import = xmlHashLookup(schema->schemasImports, namespace);
2478 if (import != NULL) {
2479 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2480 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2481 return (ret);
2482 } else
2483 ret = NULL;
2484 }
2485#ifdef DEBUG
2486 if (ret == NULL) {
2487 if (namespace == NULL)
2488 fprintf(stderr, "Unable to lookup attribute %s", name);
2489 else
2490 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2491 namespace);
2492 }
2493#endif
2494 return (ret);
2495}
2496
2497/**
2498 * xmlSchemaGetAttributeGroup:
2499 * @schema: the context of the schema
2500 * @name: the name of the attribute group
2501 * @ns: the target namespace of the attribute group
2502 *
2503 * Lookup a an attribute group in the schema or imported schemas
2504 *
2505 * Returns the attribute group definition or NULL if not found.
2506 */
2507static xmlSchemaAttributeGroupPtr
2508xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2509 const xmlChar * namespace)
2510{
2511 xmlSchemaAttributeGroupPtr ret;
2512 xmlSchemaImportPtr import = NULL;
2513
2514 if ((name == NULL) || (schema == NULL))
2515 return (NULL);
2516
2517
2518 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2519 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2520 return (ret);
2521 else
2522 ret = NULL;
2523 if (namespace == NULL)
2524 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
2525 else
2526 import = xmlHashLookup(schema->schemasImports, namespace);
2527 if (import != NULL) {
2528 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2529 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2530 return (ret);
2531 else
2532 ret = NULL;
2533 }
2534#ifdef DEBUG
2535 if (ret == NULL) {
2536 if (namespace == NULL)
2537 fprintf(stderr, "Unable to lookup attribute group %s", name);
2538 else
2539 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2540 namespace);
2541 }
2542#endif
2543 return (ret);
2544}
2545
2546/**
2547 * xmlSchemaGetGroup:
2548 * @schema: the context of the schema
2549 * @name: the name of the group
2550 * @ns: the target namespace of the group
2551 *
2552 * Lookup a group in the schema or imported schemas
2553 *
2554 * Returns the group definition or NULL if not found.
2555 */
2556static xmlSchemaTypePtr
2557xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2558 const xmlChar * namespace)
2559{
2560 xmlSchemaTypePtr ret;
2561 xmlSchemaImportPtr import = NULL;
2562
2563 if ((name == NULL) || (schema == NULL))
2564 return (NULL);
2565
2566
2567 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2568 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2569 return (ret);
2570 else
2571 ret = NULL;
2572 if (namespace == NULL)
2573 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_DEFAULT_NAMESPACE);
2574 else
2575 import = xmlHashLookup(schema->schemasImports, namespace);
2576 if (import != NULL) {
2577 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2578 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2579 return (ret);
2580 else
2581 ret = NULL;
2582 }
2583#ifdef DEBUG
2584 if (ret == NULL) {
2585 if (namespace == NULL)
2586 fprintf(stderr, "Unable to lookup group %s", name);
2587 else
2588 fprintf(stderr, "Unable to lookup group %s:%s", name,
2589 namespace);
2590 }
2591#endif
2592 return (ret);
2593}
2594
Daniel Veillard4255d502002-04-16 15:50:10 +00002595/************************************************************************
2596 * *
2597 * Parsing functions *
2598 * *
2599 ************************************************************************/
2600
2601#define IS_BLANK_NODE(n) \
2602 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2603
2604/**
2605 * xmlSchemaIsBlank:
2606 * @str: a string
2607 *
2608 * Check if a string is ignorable
2609 *
2610 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2611 */
2612static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002613xmlSchemaIsBlank(xmlChar * str)
2614{
Daniel Veillard4255d502002-04-16 15:50:10 +00002615 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002616 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002617 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002618 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002619 return (0);
2620 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002622 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002623}
2624
2625/**
2626 * xmlSchemaAddNotation:
2627 * @ctxt: a schema validation context
2628 * @schema: the schema being built
2629 * @name: the item name
2630 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002631 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002632 * *WARNING* this interface is highly subject to change
2633 *
2634 * Returns the new struture or NULL in case of error
2635 */
2636static xmlSchemaNotationPtr
2637xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002638 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002639{
2640 xmlSchemaNotationPtr ret = NULL;
2641 int val;
2642
2643 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2644 return (NULL);
2645
2646 if (schema->notaDecl == NULL)
2647 schema->notaDecl = xmlHashCreate(10);
2648 if (schema->notaDecl == NULL)
2649 return (NULL);
2650
2651 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2652 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002653 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 return (NULL);
2655 }
2656 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002657 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2659 ret);
2660 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002661 /*
2662 * TODO: This should never happen, since a unique name will be computed.
2663 * If it fails, then an other internal error must have occured.
2664 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002665 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2666 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002667 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002668 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 xmlFree(ret);
2670 return (NULL);
2671 }
2672 return (ret);
2673}
2674
2675
2676/**
2677 * xmlSchemaAddAttribute:
2678 * @ctxt: a schema validation context
2679 * @schema: the schema being built
2680 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002681 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 *
2683 * Add an XML schema Attrribute declaration
2684 * *WARNING* this interface is highly subject to change
2685 *
2686 * Returns the new struture or NULL in case of error
2687 */
2688static xmlSchemaAttributePtr
2689xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002690 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00002691{
2692 xmlSchemaAttributePtr ret = NULL;
2693 int val;
2694
2695 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2696 return (NULL);
2697
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002698#ifdef DEBUG
2699 fprintf(stderr, "Adding attribute %s\n", name);
2700 if (namespace != NULL)
2701 fprintf(stderr, " target namespace %s\n", namespace);
2702#endif
2703
Daniel Veillard4255d502002-04-16 15:50:10 +00002704 if (schema->attrDecl == NULL)
2705 schema->attrDecl = xmlHashCreate(10);
2706 if (schema->attrDecl == NULL)
2707 return (NULL);
2708
2709 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
2710 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002711 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002712 return (NULL);
2713 }
2714 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002715 ret->name = xmlDictLookup(ctxt->dict, name, -1);
2716 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002717 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002718 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002719 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002720 /*
2721 * TODO: Change this somehow, since this can be either an attribute
2722 * declaration or a particle referencing an attribute declaration.
2723 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002725 XML_SCHEMAP_REDEFINED_ATTR,
2726 "Attribute declaration '%s' is already declared.\n",
2727 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002728 xmlFree(ret);
2729 return (NULL);
2730 }
2731 return (ret);
2732}
2733
2734/**
2735 * xmlSchemaAddAttributeGroup:
2736 * @ctxt: a schema validation context
2737 * @schema: the schema being built
2738 * @name: the item name
2739 *
2740 * Add an XML schema Attrribute Group declaration
2741 *
2742 * Returns the new struture or NULL in case of error
2743 */
2744static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002745xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
2746 xmlSchemaPtr schema, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002747{
2748 xmlSchemaAttributeGroupPtr ret = NULL;
2749 int val;
2750
2751 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2752 return (NULL);
2753
2754 if (schema->attrgrpDecl == NULL)
2755 schema->attrgrpDecl = xmlHashCreate(10);
2756 if (schema->attrgrpDecl == NULL)
2757 return (NULL);
2758
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 ret =
2760 (xmlSchemaAttributeGroupPtr)
2761 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00002762 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002763 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002764 return (NULL);
2765 }
2766 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002767 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002768 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002769 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002770 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2772 XML_SCHEMAP_REDEFINED_ATTRGROUP,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002773 "Attribute group '%s' is already defined.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002774 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002775 xmlFree(ret);
2776 return (NULL);
2777 }
2778 return (ret);
2779}
2780
2781/**
2782 * xmlSchemaAddElement:
2783 * @ctxt: a schema validation context
2784 * @schema: the schema being built
2785 * @name: the type name
2786 * @namespace: the type namespace
2787 *
2788 * Add an XML schema Element declaration
2789 * *WARNING* this interface is highly subject to change
2790 *
2791 * Returns the new struture or NULL in case of error
2792 */
2793static xmlSchemaElementPtr
2794xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2795 const xmlChar * name, const xmlChar * namespace)
2796{
2797 xmlSchemaElementPtr ret = NULL;
2798 int val;
2799
2800 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2801 return (NULL);
2802
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002803#ifdef DEBUG
2804 fprintf(stderr, "Adding element %s\n", name);
2805 if (namespace != NULL)
2806 fprintf(stderr, " target namespace %s\n", namespace);
2807#endif
2808
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 if (schema->elemDecl == NULL)
2810 schema->elemDecl = xmlHashCreate(10);
2811 if (schema->elemDecl == NULL)
2812 return (NULL);
2813
2814 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
2815 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002816 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002817 return (NULL);
2818 }
2819 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002820 ret->name = xmlDictLookup(ctxt->dict, name, -1);
2821 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002822 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002823 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002824 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002825 /*
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002826 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00002827
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002828 snprintf(buf, 99, "privatieelem %d", ctxt->counter++ + 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002829 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
2830 namespace, ret);
2831 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002832 */
2833 xmlSchemaPCustomErr(ctxt,
2834 XML_SCHEMAP_REDEFINED_ELEMENT,
2835 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, NULL,
2836 "A global declaration for '%s' is already existent", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002837 xmlFree(ret);
2838 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839
Daniel Veillard4255d502002-04-16 15:50:10 +00002840 }
2841 return (ret);
2842}
2843
2844/**
2845 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002846 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002847 * @schema: the schema being built
2848 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002849 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002850 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002851 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00002852 * *WARNING* this interface is highly subject to change
2853 *
2854 * Returns the new struture or NULL in case of error
2855 */
2856static xmlSchemaTypePtr
2857xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002858 const xmlChar * name, const xmlChar * namespace)
Daniel Veillard4255d502002-04-16 15:50:10 +00002859{
2860 xmlSchemaTypePtr ret = NULL;
2861 int val;
2862
2863 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2864 return (NULL);
2865
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002866#ifdef DEBUG
2867 fprintf(stderr, "Adding type %s\n", name);
2868 if (namespace != NULL)
2869 fprintf(stderr, " target namespace %s\n", namespace);
2870#endif
2871
Daniel Veillard4255d502002-04-16 15:50:10 +00002872 if (schema->typeDecl == NULL)
2873 schema->typeDecl = xmlHashCreate(10);
2874 if (schema->typeDecl == NULL)
2875 return (NULL);
2876
2877 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
2878 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002879 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002880 return (NULL);
2881 }
2882 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002883 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002884 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002885 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002886 if (val != 0) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002887 if (ctxt->includes == 0) {
2888 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2889 XML_SCHEMAP_REDEFINED_TYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002890 "Type '%s' is already defined.\n",
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002891 name, NULL);
2892 xmlFree(ret);
2893 return (NULL);
2894 } else {
2895 xmlSchemaTypePtr prev;
2896
2897 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
2898 if (prev == NULL) {
2899 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002900 XML_ERR_INTERNAL_ERROR,
2901 "Internal error: xmlSchemaAddType, on type "
2902 "'%s'.\n",
2903 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002904 xmlFree(ret);
2905 return (NULL);
2906 }
2907 ret->redef = prev->redef;
2908 prev->redef = ret;
2909 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002910 }
2911 ret->minOccurs = 1;
2912 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00002913 ret->attributeUses = NULL;
2914 ret->attributeWildcard = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002915
2916 return (ret);
2917}
2918
2919/**
2920 * xmlSchemaAddGroup:
2921 * @ctxt: a schema validation context
2922 * @schema: the schema being built
2923 * @name: the group name
2924 *
2925 * Add an XML schema Group definition
2926 *
2927 * Returns the new struture or NULL in case of error
2928 */
2929static xmlSchemaTypePtr
2930xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002931 const xmlChar * name)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002932{
2933 xmlSchemaTypePtr ret = NULL;
2934 int val;
2935
2936 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2937 return (NULL);
2938
2939 if (schema->groupDecl == NULL)
2940 schema->groupDecl = xmlHashCreate(10);
2941 if (schema->groupDecl == NULL)
2942 return (NULL);
2943
2944 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
2945 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002946 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002947 return (NULL);
2948 }
2949 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002950 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002951 val =
2952 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
2953 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002954 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002955 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2956 XML_SCHEMAP_REDEFINED_GROUP,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002957 "Group '%s' is already defined.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002958 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002959 xmlFree(ret);
2960 return (NULL);
2961 }
2962 ret->minOccurs = 1;
2963 ret->maxOccurs = 1;
2964
2965 return (ret);
2966}
2967
Daniel Veillard3646d642004-06-02 19:19:14 +00002968/**
2969 * xmlSchemaNewWildcardNs:
2970 * @ctxt: a schema validation context
2971 *
2972 * Creates a new wildcard namespace constraint.
2973 *
2974 * Returns the new struture or NULL in case of error
2975 */
2976static xmlSchemaWildcardNsPtr
2977xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
2978{
2979 xmlSchemaWildcardNsPtr ret;
2980
2981 ret = (xmlSchemaWildcardNsPtr)
2982 xmlMalloc(sizeof(xmlSchemaWildcardNs));
2983 if (ret == NULL) {
2984 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
2985 return (NULL);
2986 }
2987 ret->value = NULL;
2988 ret->next = NULL;
2989 return (ret);
2990}
2991
2992/**
2993 * xmlSchemaAddWildcard:
2994 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002995 * Adds a wildcard. It corresponds to a
2996 * xsd:anyAttribute and is used as storage for namespace
2997 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00002998 *
2999 * Returns the new struture or NULL in case of error
3000 */
3001static xmlSchemaWildcardPtr
3002xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3003{
3004 xmlSchemaWildcardPtr ret = NULL;
3005
3006 if (ctxt == NULL)
3007 return (NULL);
3008
3009 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3010 if (ret == NULL) {
3011 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3012 return (NULL);
3013 }
3014 memset(ret, 0, sizeof(xmlSchemaWildcard));
3015 ret->minOccurs = 1;
3016 ret->maxOccurs = 1;
3017
3018 return (ret);
3019}
3020
Daniel Veillard4255d502002-04-16 15:50:10 +00003021/************************************************************************
3022 * *
3023 * Utilities for parsing *
3024 * *
3025 ************************************************************************/
3026
3027/**
3028 * xmlGetQNameProp:
3029 * @ctxt: a schema validation context
3030 * @node: a subtree containing XML Schema informations
3031 * @name: the attribute name
3032 * @namespace: the result namespace if any
3033 *
3034 * Extract a QName Attribute value
3035 *
3036 * Returns the NCName or NULL if not found, and also update @namespace
3037 * with the namespace URI
3038 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003039static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003040xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003041 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003042{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003043 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003044 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003045 const xmlChar *ret, *prefix;
3046 int len;
Daniel Veillard4255d502002-04-16 15:50:10 +00003047
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003048 *namespace = NULL;
3049 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003051 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003052
Daniel Veillardba0153a2004-04-01 10:42:31 +00003053 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003054 ns = xmlSearchNs(node->doc, node, 0);
3055 if (ns) {
3056 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3057 return (val);
3058 }
3059 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003060 ret = xmlSplitQName3(val, &len);
3061 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003063 }
3064 ret = xmlDictLookup(ctxt->dict, ret, -1);
3065 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003066
3067 ns = xmlSearchNs(node->doc, node, prefix);
3068 if (ns == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003069 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003070 "Attribute '%s': The prefix '%s' of the QName "
3071 "'%s' has no corresponding namespace declaration is scope.\n",
3072 (const xmlChar *) name, prefix);
Daniel Veillard4255d502002-04-16 15:50:10 +00003073 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003074 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003075 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003076 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003077}
3078
3079/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003080 * xmlSchemaPValAttrNodeQNameValue:
3081 * @ctxt: a schema parser context
3082 * @schema: the schema context
3083 * @ownerDes: the designation of the parent element
3084 * @ownerItem: the parent as a schema object
3085 * @value: the QName value
3086 * @local: the resulting local part if found, the attribute value otherwise
3087 * @uri: the resulting namespace URI if found
3088 *
3089 * Extracts the local name and the URI of a QName value and validates it.
3090 * This one is intended to be used on attribute values that
3091 * should resolve to schema components.
3092 *
3093 * Returns 0, in case the QName is valid, a positive error code
3094 * if not valid and -1 if an internal error occurs.
3095 */
3096static int
3097xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3098 xmlSchemaPtr schema,
3099 xmlChar **ownerDes,
3100 xmlSchemaTypePtr ownerItem,
3101 xmlAttrPtr attr,
3102 const xmlChar *value,
3103 const xmlChar **uri,
3104 const xmlChar **prefix,
3105 const xmlChar **local)
3106{
3107 const xmlChar *pref;
3108 xmlNsPtr ns;
3109 int len, ret;
3110
3111 *uri = NULL;
3112 *local = NULL;
3113 if (prefix != 0)
3114 *prefix = NULL;
3115 ret = xmlValidateQName(value, 1);
3116 if (ret > 0) {
3117 xmlSchemaPSimpleTypeErr(ctxt,
3118 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3119 ownerDes, ownerItem, (xmlNodePtr) attr,
3120 XML_SCHEMAS_QNAME, "QName", value,
3121 NULL, NULL, NULL);
3122 *local = value;
3123 return (ctxt->err);
3124 } else if (ret < 0)
3125 return (-1);
3126
3127 if (!strchr((char *) value, ':')) {
3128 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3129 if (ns)
3130 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3131 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3132 /*
3133 * This one takes care of included schemas with no
3134 * target namespace.
3135 */
3136 *uri = schema->targetNamespace;
3137 }
3138 *local = value;
3139 return (0);
3140 }
3141 /*
3142 * At this point xmlSplitQName3 has to return a local name.
3143 */
3144 *local = xmlSplitQName3(value, &len);
3145 *local = xmlDictLookup(ctxt->dict, *local, -1);
3146 pref = xmlDictLookup(ctxt->dict, value, len);
3147 if (prefix != 0)
3148 *prefix = pref;
3149 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3150 if (ns == NULL) {
3151 xmlSchemaPSimpleTypeErr(ctxt,
3152 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3153 ownerDes, ownerItem, (xmlNodePtr) attr,
3154 XML_SCHEMAS_QNAME, "QName", value,
3155 "The prefix '%s' of the value '%s' is not declared.\n",
3156 pref, value);
3157 return (ctxt->err);
3158 } else {
3159 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3160 }
3161 return (0);
3162}
3163
3164/**
3165 * xmlSchemaPValAttrNodeQName:
3166 * @ctxt: a schema parser context
3167 * @schema: the schema context
3168 * @ownerDes: the designation of the owner element
3169 * @ownerItem: the owner as a schema object
3170 * @attr: the attribute node
3171 * @local: the resulting local part if found, the attribute value otherwise
3172 * @uri: the resulting namespace URI if found
3173 *
3174 * Extracts and validates the QName of an attribute value.
3175 * This one is intended to be used on attribute values that
3176 * should resolve to schema components.
3177 *
3178 * Returns 0, in case the QName is valid, a positive error code
3179 * if not valid and -1 if an internal error occurs.
3180 */
3181static int
3182xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3183 xmlSchemaPtr schema,
3184 xmlChar **ownerDes,
3185 xmlSchemaTypePtr ownerItem,
3186 xmlAttrPtr attr,
3187 const xmlChar **uri,
3188 const xmlChar **prefix,
3189 const xmlChar **local)
3190{
3191 const xmlChar *value;
3192
3193 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3194 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3195 ownerDes, ownerItem, attr, value, uri, prefix, local));
3196}
3197
3198/**
3199 * xmlSchemaPValAttrQName:
3200 * @ctxt: a schema parser context
3201 * @schema: the schema context
3202 * @ownerDes: the designation of the parent element
3203 * @ownerItem: the owner as a schema object
3204 * @ownerElem: the parent node of the attribute
3205 * @name: the name of the attribute
3206 * @local: the resulting local part if found, the attribute value otherwise
3207 * @uri: the resulting namespace URI if found
3208 *
3209 * Extracts and validates the QName of an attribute value.
3210 *
3211 * Returns 0, in case the QName is valid, a positive error code
3212 * if not valid and -1 if an internal error occurs.
3213 */
3214static int
3215xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3216 xmlSchemaPtr schema,
3217 xmlChar **ownerDes,
3218 xmlSchemaTypePtr ownerItem,
3219 xmlNodePtr ownerElem,
3220 const char *name,
3221 const xmlChar **uri,
3222 const xmlChar **prefix,
3223 const xmlChar **local)
3224{
3225 xmlAttrPtr attr;
3226
3227 attr = xmlSchemaGetPropNode(ownerElem, name);
3228 if (attr == NULL) {
3229 *local = NULL;
3230 *uri = NULL;
3231 return (0);
3232 }
3233 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3234 ownerDes, ownerItem, attr, uri, prefix, local));
3235}
3236
3237/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 * xmlGetMaxOccurs:
3239 * @ctxt: a schema validation context
3240 * @node: a subtree containing XML Schema informations
3241 *
3242 * Get the maxOccurs property
3243 *
3244 * Returns the default if not found, or the value
3245 */
3246static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003247xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3248{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003249 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003250 int ret = 0;
3251
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003252 val = xmlSchemaGetProp(ctxt, node, "maxOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003253 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003254 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003255
3256 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003257 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003258 }
3259
3260 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003261 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003262 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003263 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003264 ret = ret * 10 + (*cur - '0');
3265 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003266 }
William M. Brack76e95df2003-10-18 16:20:14 +00003267 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003270 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003271 "The value '%s' of the attribute 'maxOccurs' is invalid.\n",
3272 val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003273 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003274 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003275 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003276}
3277
3278/**
3279 * xmlGetMinOccurs:
3280 * @ctxt: a schema validation context
3281 * @node: a subtree containing XML Schema informations
3282 *
3283 * Get the minOccurs property
3284 *
3285 * Returns the default if not found, or the value
3286 */
3287static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003288xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3289{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003290 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003291 int ret = 0;
3292
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003293 val = xmlSchemaGetProp(ctxt, node, "minOccurs");
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003295 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003296
3297 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003298 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003299 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003300 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 ret = ret * 10 + (*cur - '0');
3302 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003303 }
William M. Brack76e95df2003-10-18 16:20:14 +00003304 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003305 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003306 if (*cur != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003307 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
3308 "invalid value for minOccurs: %s\n", val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003309 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003310 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003311 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003312}
3313
3314/**
3315 * xmlGetBooleanProp:
3316 * @ctxt: a schema validation context
3317 * @node: a subtree containing XML Schema informations
3318 * @name: the attribute name
3319 * @def: the default value
3320 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003321 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003322 *
3323 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003324 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003325 */
3326static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003327xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3328 xmlChar **ownerDes,
3329 xmlSchemaTypePtr ownerItem,
3330 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003331 const char *name, int def)
3332{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003333 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003334
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003335 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003336 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003337 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003338 /*
3339 * 3.2.2.1 Lexical representation
3340 * An instance of a datatype that is defined as ·boolean·
3341 * can have the following legal literals {true, false, 1, 0}.
3342 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003343 if (xmlStrEqual(val, BAD_CAST "true"))
3344 def = 1;
3345 else if (xmlStrEqual(val, BAD_CAST "false"))
3346 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003347 else if (xmlStrEqual(val, BAD_CAST "1"))
3348 def = 1;
3349 else if (xmlStrEqual(val, BAD_CAST "0"))
3350 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003351 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003352 xmlSchemaPSimpleTypeErr(ctxt,
3353 XML_SCHEMAP_INVALID_BOOLEAN,
3354 ownerDes, ownerItem, node,
3355 XML_SCHEMAS_BOOLEAN, "(1 | 0 | true | false)", val,
3356 NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003357 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003358 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003359}
3360
3361/************************************************************************
3362 * *
3363 * Shema extraction from an Infoset *
3364 * *
3365 ************************************************************************/
3366static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3367 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003368 xmlNodePtr node,
3369 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003370static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3371 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003372 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003373 xmlNodePtr node,
3374 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003375static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3376 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003377 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003378 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003379static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3380 xmlSchemaPtr schema,
3381 xmlNodePtr node);
3382static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3383 xmlSchemaPtr schema,
3384 xmlNodePtr node);
3385static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3386 ctxt,
3387 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003388 xmlNodePtr node,
3389 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003390static xmlSchemaAttributeGroupPtr
3391xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003392 xmlSchemaPtr schema, xmlNodePtr node,
3393 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003394static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3395 xmlSchemaPtr schema,
3396 xmlNodePtr node);
3397static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3398 xmlSchemaPtr schema,
3399 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003400static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3402 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403
3404/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003405 * xmlSchemaPValAttrNode:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003406 *
3407 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003408 * @ownerDes: the designation of the parent element
3409 * @ownerItem: the schema object owner if existent
3410 * @attr: the schema attribute node being validated
3411 * @value: the value
3412 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003413 *
3414 * Validates a value against the given built-in type.
3415 * This one is intended to be used internally for validation
3416 * of schema attribute values during parsing of the schema.
3417 *
3418 * Returns 0 if the value is valid, a positive error code
3419 * number otherwise and -1 in case of an internal or API error.
3420 */
3421static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003422xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3423 xmlChar **ownerDes,
3424 xmlSchemaTypePtr ownerItem,
3425 xmlAttrPtr attr,
3426 const xmlChar *value,
3427 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003428{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003429
Daniel Veillardc0826a72004-08-10 14:17:33 +00003430 int ret = 0;
3431
3432 /*
3433 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3434 * one is really meant to be used internally, so better not.
3435 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003436 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003437 return (-1);
3438 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3439 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3440 XML_SCHEMAS_ERR_INTERNAL,
3441 "Internal error: xmlSchemaPvalueAttrNode, the given "
3442 "type '%s' is not a built-in type.\n",
3443 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003444 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003445 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003446 switch (type->builtInType) {
3447 case XML_SCHEMAS_NCNAME:
3448 ret = xmlValidateNCName(value, 1);
3449 break;
3450 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003451 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3452 XML_SCHEMAS_ERR_INTERNAL,
3453 "Internal error: xmlSchemaPvalueAttrNode, use "
3454 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3455 "for extracting QName valueues instead.\n",
3456 NULL, NULL);
3457 return (-1);
3458 case XML_SCHEMAS_ANYURI:
3459 if (value != NULL) {
3460 xmlURIPtr uri = xmlParseURI((const char *) value);
3461 if (uri == NULL)
3462 ret = 1;
3463 else
3464 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003465 }
3466 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003467 case XML_SCHEMAS_TOKEN: {
3468 const xmlChar *cur = value;
3469
3470 if (IS_BLANK_CH(*cur)) {
3471 ret = 1;
3472 } else while (*cur != 0) {
3473 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3474 ret = 1;
3475 break;
3476 } else if (*cur == ' ') {
3477 cur++;
3478 if ((*cur == 0) || (*cur == ' ')) {
3479 ret = 1;
3480 break;
3481 }
3482 } else {
3483 cur++;
3484 }
3485 }
3486 }
3487 break;
3488 case XML_SCHEMAS_LANGUAGE:
3489 if (xmlCheckLanguageID(value) != 1)
3490 ret = 1;
3491 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003492 default: {
3493 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3494 XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003495 "Internal error: xmlSchemaPvalueAttrNode, "
3496 "valueidation using the type '%s' is not implemented "
3497 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003498 type->name, NULL);
3499 return (-1);
3500 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003501 }
3502 /*
3503 * TODO: Should we use the S4S error codes instead?
3504 */
3505 if (ret > 0) {
3506 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3507 xmlSchemaPSimpleTypeErr(ctxt,
3508 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3509 ownerDes, ownerItem, (xmlNodePtr) attr,
3510 type->builtInType, NULL, value,
3511 NULL, NULL, NULL);
3512 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3513 } else {
3514 xmlSchemaPSimpleTypeErr(ctxt,
3515 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3516 ownerDes, ownerItem, (xmlNodePtr) attr,
3517 type->builtInType, NULL, value,
3518 NULL, NULL, NULL);
3519 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3520 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003521 }
3522 return (ret);
3523}
3524
3525/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003526 * xmlSchemaPValAttrNode:
3527 *
3528 * @ctxt: a schema parser context
3529 * @ownerDes: the designation of the parent element
3530 * @ownerItem: the schema object owner if existent
3531 * @attr: the schema attribute node being validated
3532 * @type: the built-in type to be validated against
3533 * @value: the resulting value if any
3534 *
3535 * Extracts and validates a value against the given built-in type.
3536 * This one is intended to be used internally for validation
3537 * of schema attribute values during parsing of the schema.
3538 *
3539 * Returns 0 if the value is valid, a positive error code
3540 * number otherwise and -1 in case of an internal or API error.
3541 */
3542static int
3543xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3544 xmlChar **ownerDes,
3545 xmlSchemaTypePtr ownerItem,
3546 xmlAttrPtr attr,
3547 xmlSchemaTypePtr type,
3548 const xmlChar **value)
3549{
3550 const xmlChar *val;
3551
3552 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3553 return (-1);
3554
3555 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3556 if (value != NULL)
3557 *value = val;
3558
3559 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3560 val, type));
3561}
3562
3563/**
3564 * xmlSchemaPValAttr:
3565 *
3566 * @ctxt: a schema parser context
3567 * @node: the element node of the attribute
3568 * @ownerDes: the designation of the parent element
3569 * @ownerItem: the schema object owner if existent
3570 * @ownerElem: the owner element node
3571 * @name: the name of the schema attribute node
3572 * @type: the built-in type to be validated against
3573 * @value: the resulting value if any
3574 *
3575 * Extracts and validates a value against the given built-in type.
3576 * This one is intended to be used internally for validation
3577 * of schema attribute values during parsing of the schema.
3578 *
3579 * Returns 0 if the value is valid, a positive error code
3580 * number otherwise and -1 in case of an internal or API error.
3581 */
3582static int
3583xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3584 xmlChar **ownerDes,
3585 xmlSchemaTypePtr ownerItem,
3586 xmlNodePtr ownerElem,
3587 const char *name,
3588 xmlSchemaTypePtr type,
3589 const xmlChar **value)
3590{
3591 xmlAttrPtr attr;
3592
3593 if ((ctxt == NULL) || (type == NULL)) {
3594 if (value != NULL)
3595 *value = NULL;
3596 return (-1);
3597 }
3598 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3599 if (value != NULL)
3600 *value = NULL;
3601 xmlSchemaPErr(ctxt, ownerElem,
3602 XML_SCHEMAS_ERR_INTERNAL,
3603 "Internal error: xmlSchemaPValAttr, the given "
3604 "type '%s' is not a built-in type.\n",
3605 type->name, NULL);
3606 return (-1);
3607 }
3608 attr = xmlSchemaGetPropNode(ownerElem, name);
3609 if (attr == NULL) {
3610 if (value != NULL)
3611 *value = NULL;
3612 return (0);
3613 }
3614 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
3615 type, value));
3616}
3617/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 * xmlSchemaParseAttrDecls:
3619 * @ctxt: a schema validation context
3620 * @schema: the schema being built
3621 * @node: a subtree containing XML Schema informations
3622 * @type: the hosting type
3623 *
3624 * parse a XML schema attrDecls declaration corresponding to
3625 * <!ENTITY % attrDecls
3626 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
3627 */
3628static xmlNodePtr
3629xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3630 xmlNodePtr child, xmlSchemaTypePtr type)
3631{
3632 xmlSchemaAttributePtr lastattr, attr;
3633
3634 lastattr = NULL;
3635 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 (IS_SCHEMA(child, "attributeGroup"))) {
3637 attr = NULL;
3638 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00003639 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003640 } else if (IS_SCHEMA(child, "attributeGroup")) {
3641 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00003642 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003643 }
3644 if (attr != NULL) {
3645 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003646 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3647 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
3648 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003649 type->attributes = attr;
3650 lastattr = attr;
3651 } else {
3652 lastattr->next = attr;
3653 lastattr = attr;
3654 }
3655 }
3656 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003657 }
3658 if (IS_SCHEMA(child, "anyAttribute")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00003659 xmlSchemaWildcardPtr wildcard;
3660
3661 wildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
3662 if (wildcard != NULL) {
3663 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
3664 ((xmlSchemaAttributeGroupPtr) type)->attributeWildcard = wildcard;
3665 else
3666 type->attributeWildcard = wildcard;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003667 }
3668 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003670 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00003671}
3672
3673/**
3674 * xmlSchemaParseAnnotation:
3675 * @ctxt: a schema validation context
3676 * @schema: the schema being built
3677 * @node: a subtree containing XML Schema informations
3678 *
3679 * parse a XML schema Attrribute declaration
3680 * *WARNING* this interface is highly subject to change
3681 *
William M. Bracke7091952004-05-11 15:09:58 +00003682 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00003683 * 1 in case of success.
3684 */
3685static xmlSchemaAnnotPtr
3686xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
3687 xmlNodePtr node)
3688{
3689 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003690 xmlNodePtr child = NULL;
3691 xmlAttrPtr attr;
3692 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003693
Daniel Veillardc0826a72004-08-10 14:17:33 +00003694 /*
3695 * INFO: S4S completed.
3696 */
3697 /*
3698 * id = ID
3699 * {any attributes with non-schema namespace . . .}>
3700 * Content: (appinfo | documentation)*
3701 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003702 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3703 return (NULL);
3704 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003705 attr = node->properties;
3706 while (attr != NULL) {
3707 if (((attr->ns == NULL) &&
3708 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
3709 ((attr->ns != NULL) &&
3710 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
3711
3712 xmlSchemaPIllegalAttrErr(ctxt,
3713 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3714 NULL, NULL, attr);
3715 }
3716 attr = attr->next;
3717 }
3718 /* TODO: Check id. */
3719
3720 /*
3721 * And now for the children...
3722 */
3723 child = node->children;
3724 while (child != NULL) {
3725 if (IS_SCHEMA(child, "appinfo")) {
3726 /* TODO: make available the content of "appinfo". */
3727 /*
3728 * source = anyURI
3729 * {any attributes with non-schema namespace . . .}>
3730 * Content: ({any})*
3731 */
3732 attr = child->properties;
3733 while (attr != NULL) {
3734 if (((attr->ns == NULL) &&
3735 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
3736 ((attr->ns != NULL) &&
3737 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003738
Daniel Veillardc0826a72004-08-10 14:17:33 +00003739 xmlSchemaPIllegalAttrErr(ctxt,
3740 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3741 NULL, NULL, attr);
3742 }
3743 attr = attr->next;
3744 }
3745 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
3746 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
3747 child = child->next;
3748 } else if (IS_SCHEMA(child, "documentation")) {
3749 /* TODO: make available the content of "documentation". */
3750 /*
3751 * source = anyURI
3752 * {any attributes with non-schema namespace . . .}>
3753 * Content: ({any})*
3754 */
3755 attr = child->properties;
3756 while (attr != NULL) {
3757 if (attr->ns == NULL) {
3758 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
3759 xmlSchemaPIllegalAttrErr(ctxt,
3760 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3761 NULL, NULL, attr);
3762 }
3763 } else {
3764 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
3765 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
3766 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
3767
3768 xmlSchemaPIllegalAttrErr(ctxt,
3769 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
3770 NULL, NULL, attr);
3771 }
3772 }
3773 attr = attr->next;
3774 }
3775 /*
3776 * Attribute "xml:lang".
3777 */
3778 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
3779 if (attr != NULL)
3780 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
3781 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
3782 child = child->next;
3783 } else {
3784 if (!barked)
3785 xmlSchemaPContentErr(ctxt,
3786 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
3787 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
3788 barked = 1;
3789 child = child->next;
3790 }
3791 }
3792
Daniel Veillard4255d502002-04-16 15:50:10 +00003793 return (ret);
3794}
3795
3796/**
3797 * xmlSchemaParseFacet:
3798 * @ctxt: a schema validation context
3799 * @schema: the schema being built
3800 * @node: a subtree containing XML Schema informations
3801 *
3802 * parse a XML schema Facet declaration
3803 * *WARNING* this interface is highly subject to change
3804 *
3805 * Returns the new type structure or NULL in case of error
3806 */
3807static xmlSchemaFacetPtr
3808xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003809 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003810{
3811 xmlSchemaFacetPtr facet;
3812 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003813 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00003814
3815 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
3816 return (NULL);
3817
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003818 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003819 if (facet == NULL) {
3820 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
3821 return (NULL);
3822 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003823 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003824 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00003825 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003826 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
3827 "Facet %s has no value\n", node->name, NULL);
3828 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00003829 return (NULL);
3830 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003832 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003833 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003834 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003835 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003836 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003837 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003838 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003839 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003840 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003841 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003842 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003843 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003844 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003845 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003846 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003847 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003848 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003849 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003850 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003851 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00003852 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
3853 } else if (IS_SCHEMA(node, "minLength")) {
3854 facet->type = XML_SCHEMA_FACET_MINLENGTH;
3855 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003856 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
3857 "Unknown facet type %s\n", node->name, NULL);
3858 xmlSchemaFreeFacet(facet);
3859 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003861 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00003862 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003863 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
3864 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
3865 const xmlChar *fixed;
3866
3867 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
3868 if (fixed != NULL) {
3869 if (xmlStrEqual(fixed, BAD_CAST "true"))
3870 facet->fixed = 1;
3871 }
3872 }
3873
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 child = node->children;
3875
3876 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003877 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
3878 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 }
3880 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
3882 "Facet %s has unexpected child content\n",
3883 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003884 }
3885 return (facet);
3886}
3887
3888/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003889 * xmlSchemaParseWildcardNs:
3890 * @ctxt: a schema parser context
3891 * @wildc: the wildcard, already created
3892 * @node: a subtree containing XML Schema informations
3893 *
3894 * Parses the attribute "processContents" and "namespace"
3895 * of a xsd:anyAttribute and xsd:any.
3896 * *WARNING* this interface is highly subject to change
3897 *
3898 * Returns 0 if everything goes fine, a positive error code
3899 * if something is not valid and -1 if an internal error occurs.
3900 */
3901static int
3902xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
3903 xmlSchemaPtr schema,
3904 xmlSchemaWildcardPtr wildc,
3905 xmlNodePtr node)
3906{
3907 const xmlChar *pc, *ns, *dictnsItem;
3908 int ret = 0;
3909 xmlChar *nsItem;
3910 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
3911 xmlAttrPtr attr;
3912
3913 pc = xmlSchemaGetProp(ctxt, node, "processContents");
3914 if ((pc == NULL)
3915 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
3916 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
3917 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
3918 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
3919 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
3920 wildc->processContents = XML_SCHEMAS_ANY_LAX;
3921 } else {
3922 xmlSchemaPSimpleTypeErr(ctxt,
3923 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
3924 NULL, NULL, node,
3925 XML_SCHEMAS_UNKNOWN, "(strict | skip | lax)", pc,
3926 NULL, NULL, NULL);
3927 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
3928 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
3929 }
3930 /*
3931 * Build the namespace constraints.
3932 */
3933 attr = xmlSchemaGetPropNode(node, "namespace");
3934 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3935 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
3936 wildc->any = 1;
3937 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
3938 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
3939 if (wildc->negNsSet == NULL) {
3940 return (-1);
3941 }
3942 wildc->negNsSet->value = schema->targetNamespace;
3943 } else {
3944 const xmlChar *end, *cur;
3945
3946 cur = ns;
3947 do {
3948 while (IS_BLANK_CH(*cur))
3949 cur++;
3950 end = cur;
3951 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
3952 end++;
3953 if (end == cur)
3954 break;
3955 nsItem = xmlStrndup(cur, end - cur);
3956 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
3957 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
3958 xmlSchemaPSimpleTypeErr(ctxt,
3959 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
3960 NULL, NULL, (xmlNodePtr) attr,
3961 XML_SCHEMAS_UNKNOWN,
3962 "((##any | ##other) | List of (anyURI | "
3963 "(##targetNamespace | ##local)))",
3964 nsItem, NULL, NULL, NULL);
3965 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
3966 } else {
3967 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
3968 dictnsItem = schema->targetNamespace;
3969 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
3970 dictnsItem = NULL;
3971 } else {
3972 /*
3973 * Validate the item (anyURI).
3974 */
3975 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
3976 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
3977 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
3978 }
3979 /*
3980 * Avoid dublicate namespaces.
3981 */
3982 tmp = wildc->nsSet;
3983 while (tmp != NULL) {
3984 if (dictnsItem == tmp->value)
3985 break;
3986 tmp = tmp->next;
3987 }
3988 if (tmp == NULL) {
3989 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
3990 if (tmp == NULL) {
3991 xmlFree(nsItem);
3992 return (-1);
3993 }
3994 tmp->value = dictnsItem;
3995 tmp->next = NULL;
3996 if (wildc->nsSet == NULL)
3997 wildc->nsSet = tmp;
3998 else
3999 lastNs->next = tmp;
4000 lastNs = tmp;
4001 }
4002
4003 }
4004 xmlFree(nsItem);
4005 cur = end;
4006 } while (*cur != 0);
4007 }
4008 return (ret);
4009}
4010/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004011 * xmlSchemaParseAny:
4012 * @ctxt: a schema validation context
4013 * @schema: the schema being built
4014 * @node: a subtree containing XML Schema informations
4015 *
4016 * parse a XML schema Any declaration
4017 * *WARNING* this interface is highly subject to change
4018 *
4019 * Returns the new type structure or NULL in case of error
4020 */
4021static xmlSchemaTypePtr
4022xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4023 xmlNodePtr node)
4024{
4025 xmlSchemaTypePtr type;
4026 xmlNodePtr child = NULL;
4027 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004028 xmlSchemaWildcardPtr wildc;
Daniel Veillard4255d502002-04-16 15:50:10 +00004029
4030 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4031 return (NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004032 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004033 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004034 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004035 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004036 type->node = node;
4037 type->type = XML_SCHEMA_TYPE_ANY;
Daniel Veillard4255d502002-04-16 15:50:10 +00004038 type->minOccurs = xmlGetMinOccurs(ctxt, node);
4039 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004040 wildc = xmlSchemaAddWildcard(ctxt);
4041 /*
4042 * This is not nice, since it is won't be used as a attribute wildcard,
4043 * but better than adding a field to the structure.
4044 */
4045 type->attributeWildcard = wildc;
4046 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
4047 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004048 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004049 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4050 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004051 }
4052 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 xmlSchemaPErr2(ctxt, node, child,
4054 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4055 "Sequence %s has unexpected content\n", type->name,
4056 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004057 }
4058
4059 return (type);
4060}
4061
4062/**
4063 * xmlSchemaParseNotation:
4064 * @ctxt: a schema validation context
4065 * @schema: the schema being built
4066 * @node: a subtree containing XML Schema informations
4067 *
4068 * parse a XML schema Notation declaration
4069 *
4070 * Returns the new structure or NULL in case of error
4071 */
4072static xmlSchemaNotationPtr
4073xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004074 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004075{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004076 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004077 xmlSchemaNotationPtr ret;
4078 xmlNodePtr child = NULL;
4079
4080 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4081 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004082 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004083 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004084 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4085 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004086 return (NULL);
4087 }
4088 ret = xmlSchemaAddNotation(ctxt, schema, name);
4089 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004090 return (NULL);
4091 }
4092 child = node->children;
4093 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004094 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4095 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 }
4097 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004098 xmlSchemaPErr2(ctxt, node, child,
4099 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4100 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004101 }
4102
4103 return (ret);
4104}
4105
4106/**
4107 * xmlSchemaParseAnyAttribute:
4108 * @ctxt: a schema validation context
4109 * @schema: the schema being built
4110 * @node: a subtree containing XML Schema informations
4111 *
4112 * parse a XML schema AnyAttrribute declaration
4113 * *WARNING* this interface is highly subject to change
4114 *
4115 * Returns an attribute def structure or NULL
4116 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004117static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004118xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4119 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004120{
Daniel Veillard3646d642004-06-02 19:19:14 +00004121 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004122 xmlNodePtr child = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004123
4124 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4125 return (NULL);
4126
Daniel Veillard3646d642004-06-02 19:19:14 +00004127 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004128 if (ret == NULL) {
4129 return (NULL);
4130 }
William M. Bracke7091952004-05-11 15:09:58 +00004131 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004132 ret->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004133 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4134 xmlSchemaFreeWildcard(ret);
4135 return (NULL);
4136 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004137 child = node->children;
4138 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004139 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4140 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004141 }
4142 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004143 /* TODO: Change the error code. */
4144 xmlSchemaPContentErr(ctxt,
4145 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,
4146 NULL, NULL, node, child,
4147 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004148 }
4149
4150 return (ret);
4151}
4152
4153
4154/**
4155 * xmlSchemaParseAttribute:
4156 * @ctxt: a schema validation context
4157 * @schema: the schema being built
4158 * @node: a subtree containing XML Schema informations
4159 *
4160 * parse a XML schema Attrribute declaration
4161 * *WARNING* this interface is highly subject to change
4162 *
William M. Bracke7091952004-05-11 15:09:58 +00004163 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004164 */
4165static xmlSchemaAttributePtr
4166xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004167 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004168{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004169 const xmlChar *name, *attrValue;
4170 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004172 xmlNodePtr child = NULL;
4173 xmlAttrPtr attr, nameAttr;
4174 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004175
4176 /*
4177 * Note that the w3c spec assumes the schema to be validated with schema
4178 * for schemas beforehand.
4179 *
4180 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004181 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004182
4183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4184 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004185 attr = xmlSchemaGetPropNode(node, "ref");
4186 nameAttr = xmlSchemaGetPropNode(node, "name");
4187
4188 if ((attr == NULL) && (nameAttr == NULL)) {
4189 /*
4190 * 3.2.3 : 3.1
4191 * One of ref or name must be present, but not both
4192 */
4193 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4194 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4195 "One of the attributes 'ref' or 'name' must be present");
4196 return (NULL);
4197 }
4198 if ((topLevel) || (attr == NULL)) {
4199 if (nameAttr == NULL) {
4200 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4201 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4202 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004203 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004204 }
4205 } else
4206 isRef = 1;
4207
4208 if (isRef) {
4209 char buf[100];
4210 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4211
4212 /*
4213 * Parse as attribute reference.
4214 */
4215 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4216 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4217 &refPrefix, &ref) != 0) {
4218 return (NULL);
4219 }
4220 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4221 name = (const xmlChar *) buf;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004222 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004223 if (ret == NULL) {
4224 if (repName != NULL)
4225 xmlFree(repName);
4226 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004227 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004228 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4229 ret->node = node;
4230 ret->refNs = refNs;
4231 ret->refPrefix = refPrefix;
4232 ret->ref = ref;
4233 /*
4234 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4235 */
4236 if (nameAttr != NULL)
4237 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4238 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4239 "ref", "name");
4240 /*
4241 * Check for illegal attributes.
4242 */
4243 attr = node->properties;
4244 while (attr != NULL) {
4245 if (attr->ns == NULL) {
4246 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4247 xmlStrEqual(attr->name, BAD_CAST "form")) {
4248 /*
4249 * 3.2.3 : 3.2
4250 * If ref is present, then all of <simpleType>,
4251 * form and type must be absent.
4252 */
4253 xmlSchemaPIllegalAttrErr(ctxt,
4254 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4255 (xmlSchemaTypePtr) ret, attr);
4256 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4257 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4258 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4259 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4260 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4261 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4262 xmlSchemaPIllegalAttrErr(ctxt,
4263 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4264 &repName, (xmlSchemaTypePtr) ret, attr);
4265 }
4266 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4267 xmlSchemaPIllegalAttrErr(ctxt,
4268 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4269 &repName, (xmlSchemaTypePtr) ret, attr);
4270 }
4271 attr = attr->next;
4272 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004273 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004274 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004275
4276 /*
4277 * Parse as attribute declaration.
4278 */
4279 if (xmlSchemaPValAttrNode(ctxt,
4280 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4281 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4282 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004283 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004284 /*
4285 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4286 */
4287 /*
4288 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4289 */
4290 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4291 xmlSchemaPSimpleTypeErr(ctxt,
4292 XML_SCHEMAP_NO_XMLNS,
4293 &repName, NULL, (xmlNodePtr) nameAttr,
4294 XML_SCHEMAS_NCNAME, "NCName", NULL,
4295 "The value must not match 'xmlns'",
4296 NULL, NULL);
4297 if (repName != NULL)
4298 xmlFree(repName);
4299 return (NULL);
4300 }
4301 /*
4302 * Evaluate the target namespace
4303 */
William M. Bracke7091952004-05-11 15:09:58 +00004304 if (schema->targetNamespace != NULL) {
4305 if (topLevel) {
4306 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004307 } else {
4308 attr = xmlSchemaGetPropNode(node, "form");
4309 if (attr != NULL) {
4310 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4311 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4312 ns = schema->targetNamespace;
4313 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4314 xmlSchemaPSimpleTypeErr(ctxt,
4315 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4316 &repName, NULL, (xmlNodePtr) attr,
4317 XML_SCHEMAS_UNKNOWN, "(qualified | unqualified)",
4318 attrValue, NULL, NULL, NULL);
4319 }
4320 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4321 ns = schema->targetNamespace;
4322 }
4323 }
William M. Bracke7091952004-05-11 15:09:58 +00004324 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004325 if (ret == NULL) {
4326 if (repName != NULL)
4327 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004328 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004329 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004330 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4331 ret->node = node;
4332 if (topLevel)
4333 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4334 /*
4335 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4336 */
4337 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4338 xmlSchemaPCustomErr(ctxt,
4339 XML_SCHEMAP_NO_XSI,
4340 &repName, (xmlSchemaTypePtr) ret, node,
4341 "The target namespace must not match '%s'",
4342 xmlSchemaInstanceNs);
4343 }
4344 /*
4345 * Check for illegal attributes.
4346 */
4347 attr = node->properties;
4348 while (attr != NULL) {
4349 if (attr->ns == NULL) {
4350 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4351 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4352 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4353 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4354 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4355 if ((topLevel) ||
4356 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4357 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4358 xmlSchemaPIllegalAttrErr(ctxt,
4359 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4360 &repName, (xmlSchemaTypePtr) ret, attr);
4361 }
4362 }
4363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4364 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4365 &repName, (xmlSchemaTypePtr) ret, attr);
4366 }
4367 attr = attr->next;
4368 }
4369 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4370 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004371 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004372 /* TODO: Check ID. */
4373 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004374 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004375 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004377 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4378 if (ret->defValue != NULL)
4379 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4380 /*
4381 * Attribute "default".
4382 */
4383 attr = xmlSchemaGetPropNode(node, "default");
4384 if (attr != NULL) {
4385 /*
4386 * 3.2.3 : 1
4387 * default and fixed must not both be present.
4388 */
4389 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4390 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4391 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4392 } else
4393 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4394 }
4395 if (topLevel == 0) {
4396 /*
4397 * Attribute "use".
4398 */
4399 attr = xmlSchemaGetPropNode(node, "use");
4400 if (attr != NULL) {
4401 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4402 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4403 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4404 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4405 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4406 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4407 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4408 else
4409 xmlSchemaPSimpleTypeErr(ctxt,
4410 XML_SCHEMAP_INVALID_ATTR_USE,
4411 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
4412 XML_SCHEMAS_UNKNOWN, "(optional | prohibited | required)",
4413 attrValue, NULL, NULL, NULL);
4414 } else
4415 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4416 /*
4417 * 3.2.3 : 2
4418 * If default and use are both present, use must have
4419 * the actual value optional.
4420 */
4421 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4422 (ret->defValue != NULL) &&
4423 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4424 xmlSchemaPSimpleTypeErr(ctxt,
4425 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4426 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
4427 XML_SCHEMAS_UNKNOWN, "(optional | prohibited | required)", NULL,
4428 "The value must be 'optional' if the attribute "
4429 "'default' is present as well", NULL, NULL);
4430 }
4431 }
4432 /*
4433 * And now for the children...
4434 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004435 child = node->children;
4436 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4438 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004439 }
4440 if (isRef) {
4441 if (child != NULL) {
4442 if (IS_SCHEMA(child, "simpleType"))
4443 /*
4444 * 3.2.3 : 3.2
4445 * If ref is present, then all of <simpleType>,
4446 * form and type must be absent.
4447 */
4448 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4449 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4450 "(annotation?)");
4451 else
4452 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4453 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4454 "(annotation?)");
4455 }
4456 } else {
4457 if (IS_SCHEMA(child, "simpleType")) {
4458 if (ret->typeName != NULL) {
4459 /*
4460 * 3.2.3 : 4
4461 * type and <simpleType> must not both be present.
4462 */
4463 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4464 &repName, (xmlSchemaTypePtr) ret, node, child,
4465 "The attribute 'type' and the <simpleType> child "
4466 "are mutually exclusive", NULL);
4467 } else
4468 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4469 child = child->next;
4470 }
4471 if (child != NULL)
4472 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4473 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4474 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004475 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004476 /*
4477 * Cleanup.
4478 */
4479 if (repName != NULL)
4480 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 return (ret);
4482}
4483
4484/**
4485 * xmlSchemaParseAttributeGroup:
4486 * @ctxt: a schema validation context
4487 * @schema: the schema being built
4488 * @node: a subtree containing XML Schema informations
4489 *
4490 * parse a XML schema Attribute Group declaration
4491 * *WARNING* this interface is highly subject to change
4492 *
4493 * Returns the attribute group or NULL in case of error.
4494 */
4495static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004496xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004497 xmlSchemaPtr schema, xmlNodePtr node,
4498 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004499{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004500 const xmlChar *name, *refNs = NULL, *ref = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004501 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004503 const xmlChar *oldcontainer;
4504 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00004505
4506 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4507 return (NULL);
4508 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004509 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004510 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
4512 if (ref == NULL) {
4513 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004514 XML_SCHEMAP_ATTRGRP_NONAME_NOREF,
4515 "Attribute group or particle: One of the attributes 'name' "
4516 "or 'ref' must be present.\n", NULL,
4517 NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518 return (NULL);
4519 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004520 snprintf(buf, 99, "anonattrgroup %d", ctxt->counter++ + 1);
4521 name = (const xmlChar *) buf;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004522 if (name == NULL) {
4523 xmlSchemaPErrMemory(ctxt, "creating attribute group", node);
4524 return (NULL);
4525 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004526 }
4527 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name);
4528 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 return (NULL);
4530 }
4531 ret->ref = ref;
4532 ret->refNs = refNs;
Daniel Veillard13e04c62002-04-23 17:51:29 +00004533 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00004534 if (topLevel)
4535 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00004536 ret->node = node;
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 child = node->children;
4538 ctxt->container = name;
4539 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004540 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4541 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004542 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004543 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004544 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004545 xmlSchemaPErr2(ctxt, node, child,
4546 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004547 "Attribute group '%s' has unexpected content.\n", name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004548 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004549 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 ctxt->container = oldcontainer;
4551 return (ret);
4552}
4553
4554/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004555 * xmlSchemaPValAttrBlockFinal:
4556 * @value: the value
4557 * @flags: the flags to be modified
4558 * @flagAll: the specific flag for "#all"
4559 * @flagExtension: the specific flag for "extension"
4560 * @flagRestriction: the specific flag for "restriction"
4561 * @flagSubstitution: the specific flag for "substitution"
4562 * @flagList: the specific flag for "list"
4563 * @flagUnion: the specific flag for "union"
4564 *
4565 * Validates the value of the attribute "final" and "block". The value
4566 * is converted into the specified flag values and returned in @flags.
4567 *
4568 * Returns 0 if the value is valid, 1 otherwise.
4569 */
4570
4571static int
4572xmlSchemaPValAttrBlockFinal(const xmlChar *value,
4573 int *flags,
4574 int flagAll,
4575 int flagExtension,
4576 int flagRestriction,
4577 int flagSubstitution,
4578 int flagList,
4579 int flagUnion)
4580{
4581 int ret = 0;
4582
4583 /*
4584 * TODO: This does not check for dublicate entries.
4585 */
4586 if (xmlStrEqual(value, BAD_CAST "#all")) {
4587 if (flagAll != -1)
4588 *flags |= flagAll;
4589 else {
4590 if (flagExtension != -1)
4591 *flags |= flagExtension;
4592 if (flagRestriction != -1)
4593 *flags |= flagRestriction;
4594 if (flagSubstitution != -1)
4595 *flags |= flagSubstitution;
4596 if (flagList != -1)
4597 *flags |= flagList;
4598 if (flagUnion != -1)
4599 *flags |= flagUnion;
4600 }
4601 } else {
4602 const xmlChar *end, *cur = value;
4603 xmlChar *item;
4604
4605 do {
4606 while (IS_BLANK_CH(*cur))
4607 cur++;
4608 end = cur;
4609 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4610 end++;
4611 if (end == cur)
4612 break;
4613 item = xmlStrndup(cur, end - cur);
4614 if (xmlStrEqual(item, BAD_CAST "extension")) {
4615 if (flagExtension != -1) {
4616 if ((*flags & flagExtension) == 0)
4617 *flags |= flagExtension;
4618 } else
4619 ret = 1;
4620 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
4621 if (flagRestriction != -1) {
4622 if ((*flags & flagRestriction) == 0)
4623 *flags |= flagRestriction;
4624 } else
4625 ret = 1;
4626 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
4627 if (flagSubstitution != -1) {
4628 if ((*flags & flagSubstitution) == 0)
4629 *flags |= flagSubstitution;
4630 } else
4631 ret = 1;
4632 } else if (xmlStrEqual(item, BAD_CAST "list")) {
4633 if (flagList != -1) {
4634 if ((*flags & flagList) == 0)
4635 *flags |= flagList;
4636 } else
4637 ret = 1;
4638 } else if (xmlStrEqual(item, BAD_CAST "union")) {
4639 if (flagUnion != -1) {
4640 if ((*flags & flagUnion) == 0)
4641 *flags |= flagUnion;
4642 } else
4643 ret = 1;
4644 } else
4645 ret = 1;
4646 if (item != NULL)
4647 xmlFree(item);
4648 cur = end;
4649 } while ((ret == 0) && (*cur != 0));
4650 }
4651
4652 return (ret);
4653}
4654
4655/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004656 * xmlSchemaParseElement:
4657 * @ctxt: a schema validation context
4658 * @schema: the schema being built
4659 * @node: a subtree containing XML Schema informations
4660 *
4661 * parse a XML schema Element declaration
4662 * *WARNING* this interface is highly subject to change
4663 *
William M. Bracke7091952004-05-11 15:09:58 +00004664 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004665 */
4666static xmlSchemaElementPtr
4667xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004668 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004669{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004670 const xmlChar *name = NULL;
4671 const xmlChar *attrValue;
4672 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 xmlSchemaElementPtr ret;
4674 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004675 const xmlChar *oldcontainer;
4676 xmlAttrPtr attr, nameAttr;
4677 int minOccurs, maxOccurs;
4678 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004679
4680 /* 3.3.3 Constraints on XML Representations of Element Declarations */
4681 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004682
Daniel Veillard4255d502002-04-16 15:50:10 +00004683 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4684 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004685
Daniel Veillardc0826a72004-08-10 14:17:33 +00004686 oldcontainer = ctxt->container;
4687
4688 nameAttr = xmlSchemaGetPropNode(node, "name");
4689 attr = xmlSchemaGetPropNode(node, "ref");
4690 if ((topLevel) || (attr == NULL)) {
4691 if (nameAttr == NULL) {
4692 xmlSchemaPMissingAttrErr(ctxt,
4693 XML_SCHEMAP_S4S_ATTR_MISSING,
4694 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
4695 "name", NULL);
4696 return (NULL);
4697 }
4698 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
4699 } else {
4700 isRef = 1;
4701
4702 }
4703 /*
4704 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
4705 * to no component at all
4706 * TODO: It might be better to validate the element, even if it won't be
4707 * used.
4708 */
4709 minOccurs = xmlGetMinOccurs(ctxt, node);
4710 maxOccurs = xmlGetMaxOccurs(ctxt, node);
4711 if ((minOccurs == 0) && (maxOccurs == 0))
4712 return (NULL);
4713 /*
4714 * If we get a "ref" attribute on a local <element> we will assume it's
4715 * a reference - even if there's a "name" attribute; this seems to be more
4716 * robust.
4717 */
4718 if (isRef) {
4719 char buf[100];
4720 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
4721
4722 /*
4723 * Parse as a particle.
4724 */
4725 xmlSchemaPValAttrNodeQName(ctxt, schema,
4726 (xmlChar **) &xmlSchemaElemDesAttrRef,
4727 NULL, attr, &refNs, &refPrefix, &ref);
4728
4729 snprintf(buf, 99, "#eRef %d", ctxt->counter++ + 1);
4730 name = (const xmlChar *) buf;
4731 ret = xmlSchemaAddElement(ctxt, schema, name, NULL);
4732 if (ret == NULL) {
4733 if (repName != NULL)
4734 xmlFree(repName);
4735 return (NULL);
4736 }
4737 ret->type = XML_SCHEMA_TYPE_ELEMENT;
4738 ret->node = node;
4739 ret->ref = ref;
4740 ret->refNs = refNs;
4741 ret->refPrefix = refPrefix;
4742 ret->flags |= XML_SCHEMAS_ELEM_REF;
4743 /*
4744 * Check for illegal attributes.
4745 */
4746 /*
4747 * 3.3.3 : 2.1
4748 * One of ref or name must be present, but not both
4749 */
4750 if (nameAttr != NULL) {
4751 xmlSchemaPMutualExclAttrErr(ctxt,
4752 XML_SCHEMAP_SRC_ELEMENT_2_1,
4753 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4754 "ref", "name");
4755 }
4756 /* 3.3.3 : 2.2 */
4757 attr = node->properties;
4758 while (attr != NULL) {
4759 if (attr->ns == NULL) {
4760 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4761 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4762 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
4763 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
4764 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
4765 xmlSchemaPCustomAttrErr(ctxt,
4766 XML_SCHEMAP_SRC_ELEMENT_2_2,
4767 &repName, (xmlSchemaTypePtr) ret, attr,
4768 "Only the attributes 'minOccurs', 'maxOccurs' and "
4769 "'id' are allowed in addition to 'ref'");
4770 break;
4771 }
4772 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4773 xmlSchemaPIllegalAttrErr(ctxt,
4774 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4775 &repName, (xmlSchemaTypePtr) ret, attr);
4776 }
4777 attr = attr->next;
4778 }
4779 } else {
4780 const xmlChar *ns = NULL, *fixed;
4781
4782 /*
4783 * Parse as an element declaration.
4784 */
4785 if (xmlSchemaPValAttrNode(ctxt,
4786 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
4787 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
4788 return (NULL);
4789 /*
4790 * Evaluate the target namespace.
4791 */
William M. Bracke7091952004-05-11 15:09:58 +00004792 if (schema->targetNamespace != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004793 if (topLevel) {
William M. Bracke7091952004-05-11 15:09:58 +00004794 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004795 } else {
4796 attr = xmlSchemaGetPropNode(node, "form");
4797 if (attr != NULL) {
4798 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4799 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4800 ns = schema->targetNamespace;
4801 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4802 xmlSchemaPSimpleTypeErr(ctxt,
4803 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4804 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL,
4805 (xmlNodePtr) attr,
4806 XML_SCHEMAS_UNKNOWN, "(qualified | unqualified)",
4807 attrValue, NULL, NULL, NULL);
4808 }
4809 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
William M. Bracke7091952004-05-11 15:09:58 +00004810 ns = schema->targetNamespace;
William M. Bracke7091952004-05-11 15:09:58 +00004811 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004812 }
William M. Bracke7091952004-05-11 15:09:58 +00004813 ret = xmlSchemaAddElement(ctxt, schema, name, ns);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004814 if (ret == NULL) {
4815 if (repName != NULL)
4816 xmlFree(repName);
4817 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004818 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004819 ret->type = XML_SCHEMA_TYPE_ELEMENT;
4820 ret->node = node;
4821 /*
4822 * Check for illegal attributes.
4823 */
William M. Bracke7091952004-05-11 15:09:58 +00004824 attr = node->properties;
4825 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004826 if (attr->ns == NULL) {
4827 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4828 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
4829 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4830 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4831 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4832 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
4833 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
4834 if (topLevel == 0) {
4835 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
4836 /*
4837 * 3.3.6 : 3 If there is a non-·absent· {substitution
4838 * group affiliation}, then {scope} must be global.
4839 * TODO: This one is redundant, since the S4S does
4840 * prohibit this attribute on local declarations already;
4841 * so why an explicit error code? Weird spec.
4842 */
4843 xmlSchemaPIllegalAttrErr(ctxt,
4844 XML_SCHEMAP_E_PROPS_CORRECT_3,
4845 &repName, (xmlSchemaTypePtr) ret, attr);
4846 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
4847 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
4848 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00004849
Daniel Veillardc0826a72004-08-10 14:17:33 +00004850 xmlSchemaPIllegalAttrErr(ctxt,
4851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4852 &repName, (xmlSchemaTypePtr) ret, attr);
4853 }
4854 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
4855 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
4856 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
4857
4858 xmlSchemaPIllegalAttrErr(ctxt,
4859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4860 &repName, (xmlSchemaTypePtr) ret, attr);
4861 }
4862 }
4863 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4864
4865 xmlSchemaPIllegalAttrErr(ctxt,
4866 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4867 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00004868 }
4869 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004870 }
William M. Bracke7091952004-05-11 15:09:58 +00004871 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004872 * Extract/validate attributes.
4873 */
4874 if (topLevel) {
4875 /*
4876 * Process top attributes of global element declarations here.
4877 */
4878 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
4879 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
4880 xmlSchemaPValAttrQName(ctxt, schema, &repName,
4881 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
4882 &(ret->substGroupNs), NULL, &(ret->substGroup));
4883 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
4884 node, "abstract", 0))
4885 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
4886 /*
4887 * Attribute "final".
4888 */
4889 attr = xmlSchemaGetPropNode(node, "final");
4890 if (attr == NULL) {
4891 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
4892 } else {
4893 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4894 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
4895 -1,
4896 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
4897 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
4898 xmlSchemaPSimpleTypeErr(ctxt,
4899 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4900 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
4901 XML_SCHEMAS_UNKNOWN, "(#all | List of (extension | restriction))",
4902 attrValue, NULL, NULL, NULL);
4903 }
4904 }
4905 }
4906 /*
4907 * Attribute "block".
4908 */
4909 attr = xmlSchemaGetPropNode(node, "block");
4910 if (attr == NULL) {
4911 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
4912 } else {
4913 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4914 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
4915 -1,
4916 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
4917 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
4918 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
4919 xmlSchemaPSimpleTypeErr(ctxt,
4920 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4921 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
4922 XML_SCHEMAS_UNKNOWN, "(#all | List of (extension | "
4923 "restriction | substitution))", attrValue,
4924 NULL, NULL, NULL);
4925 }
4926 }
4927 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
4928 node, "nillable", 0))
4929 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930
Daniel Veillardc0826a72004-08-10 14:17:33 +00004931 xmlSchemaPValAttrQName(ctxt, schema,
4932 &repName, (xmlSchemaTypePtr) ret, node,
4933 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00004934
Daniel Veillardc0826a72004-08-10 14:17:33 +00004935 ret->value = xmlSchemaGetProp(ctxt, node, "default");
4936 attr = xmlSchemaGetPropNode(node, "fixed");
4937 if (attr != NULL) {
4938 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4939 if (ret->value != NULL) {
4940 /*
4941 * 3.3.3 : 1
4942 * default and fixed must not both be present.
4943 */
4944 xmlSchemaPMutualExclAttrErr(ctxt,
4945 XML_SCHEMAP_SRC_ELEMENT_1,
4946 &repName, (xmlSchemaTypePtr) ret, attr,
4947 "default", "fixed");
4948 } else {
4949 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
4950 ret->value = fixed;
4951 }
4952 }
4953 }
4954 /*
4955 * Extract/validate common attributes.
4956 */
4957 /* TODO: Check ID: */
4958 ret->id = xmlSchemaGetProp(ctxt, node, "id");
4959 ret->minOccurs = minOccurs;
4960 ret->maxOccurs = maxOccurs;
4961 if ((topLevel != 1) && (ret->maxOccurs != UNBOUNDED)) {
4962 /*
4963 * TODO: Maby we should better not create the element/particle,
4964 * if min/max is invalid, since it could confuse the build of the
4965 * content model.
4966 */
4967 /*
4968 * 3.9.6 Schema Component Constraint: Particle Correct
4969 *
4970 */
4971 if (maxOccurs < 1) {
4972 /*
4973 * 2.2 {max occurs} must be greater than or equal to 1.
4974 */
4975 xmlSchemaPCustomAttrErr(ctxt,
4976 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4977 &repName, (xmlSchemaTypePtr) ret,
4978 xmlSchemaGetPropNode(node, "maxOccurs"),
4979 "The value must be greater than or equal to 1");
4980 } else if (minOccurs > maxOccurs) {
4981 /*
4982 * 2.1 {min occurs} must not be greater than {max occurs}.
4983 */
4984 xmlSchemaPCustomAttrErr(ctxt,
4985 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4986 &repName, (xmlSchemaTypePtr) ret,
4987 xmlSchemaGetPropNode(node, "minOccurs"),
4988 "The value must not be greater than the value of 'maxOccurs'");
4989 }
4990 }
4991
4992 /*
4993 * And now for the children...
4994 */
4995 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 child = node->children;
4997 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004998 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4999 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005001 if (isRef) {
5002 if (child != NULL) {
5003 xmlSchemaPContentErr(ctxt,
5004 XML_SCHEMAP_SRC_ELEMENT_2_2,
5005 &repName, (xmlSchemaTypePtr) ret, node, child,
5006 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005007 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005008 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005009 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005010 /*
5011 * 3.3.3 : 3
5012 * "type" and either <simpleType> or <complexType> are mutually
5013 * exclusive
5014 */
William M. Bracke7091952004-05-11 15:09:58 +00005015 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005016 xmlSchemaPContentErr(ctxt,
5017 XML_SCHEMAP_SRC_ELEMENT_3,
5018 &repName, (xmlSchemaTypePtr) ret, node, child,
5019 "The attribute 'type' and the <complexType> child are "
5020 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005021 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005022 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005023 child = child->next;
5024 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005025 /*
5026 * 3.3.3 : 3
5027 * "type" and either <simpleType> or <complexType> are
5028 * mutually exclusive
5029 */
William M. Bracke7091952004-05-11 15:09:58 +00005030 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005031 xmlSchemaPContentErr(ctxt,
5032 XML_SCHEMAP_SRC_ELEMENT_3,
5033 &repName, (xmlSchemaTypePtr) ret, node, child,
5034 "The attribute 'type' and the <simpleType> child are "
5035 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005036 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005037 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005038 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005039 }
William M. Bracke7091952004-05-11 15:09:58 +00005040 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005041 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005042 TODO child = child->next;
5043 }
5044 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045 xmlSchemaPContentErr(ctxt,
5046 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5047 &repName, (xmlSchemaTypePtr) ret, node, child,
5048 NULL, "(annotation?, ((simpleType | complexType)?, "
5049 "(unique | key | keyref)*))");
5050 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005051
Daniel Veillardc0826a72004-08-10 14:17:33 +00005052 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005053 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005054 /*
5055 * Cleanup.
5056 */
5057 if (repName != NULL)
5058 xmlFree(repName);
5059 /*
5060 * NOTE: Element Declaration Representation OK 4. will be checked at a
5061 * different layer.
5062 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 return (ret);
5064}
5065
5066/**
5067 * xmlSchemaParseUnion:
5068 * @ctxt: a schema validation context
5069 * @schema: the schema being built
5070 * @node: a subtree containing XML Schema informations
5071 *
5072 * parse a XML schema Union definition
5073 * *WARNING* this interface is highly subject to change
5074 *
William M. Bracke7091952004-05-11 15:09:58 +00005075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005076 * 1 in case of success.
5077 */
5078static xmlSchemaTypePtr
5079xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005080 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005081{
5082 xmlSchemaTypePtr type, subtype, last = NULL;
5083 xmlNodePtr child = NULL;
5084 xmlChar name[30];
5085
5086 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5087 return (NULL);
5088
5089
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005090 snprintf((char *) name, 30, "union %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005091 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 if (type == NULL)
5093 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005094 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005095 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005096 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005097 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
Daniel Veillard4255d502002-04-16 15:50:10 +00005098
5099 child = node->children;
5100 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005101 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5102 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005103 }
5104 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005105 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005106 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005107 if (subtype != NULL) {
5108 if (last == NULL) {
5109 type->subtypes = subtype;
5110 last = subtype;
5111 } else {
5112 last->next = subtype;
5113 last = subtype;
5114 }
5115 last->next = NULL;
5116 }
5117 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005118 }
5119 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005120 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_UNION_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005121 "<union> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005123 }
5124 return (type);
5125}
5126
5127/**
5128 * xmlSchemaParseList:
5129 * @ctxt: a schema validation context
5130 * @schema: the schema being built
5131 * @node: a subtree containing XML Schema informations
5132 *
5133 * parse a XML schema List definition
5134 * *WARNING* this interface is highly subject to change
5135 *
William M. Bracke7091952004-05-11 15:09:58 +00005136 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005137 * 1 in case of success.
5138 */
5139static xmlSchemaTypePtr
5140xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005141 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005142{
5143 xmlSchemaTypePtr type, subtype;
5144 xmlNodePtr child = NULL;
5145 xmlChar name[30];
5146
5147 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5148 return (NULL);
5149
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005150 snprintf((char *) name, 30, "list %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005151 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 if (type == NULL)
5153 return (NULL);
5154 type->node = node;
5155 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005156 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005157
5158 child = node->children;
5159 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005160 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5161 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005162 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005163 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5164 node, "itemType", &(type->baseNs), NULL, &(type->base));
Daniel Veillard4255d502002-04-16 15:50:10 +00005165 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005166 if (IS_SCHEMA(child, "simpleType")) {
5167 subtype = (xmlSchemaTypePtr)
5168 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5169 type->subtypes = subtype;
5170 /*
5171 * This is a hack to save the information that a local
5172 * simple type was defined.
5173 */
5174 type->baseType = subtype;
5175 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 }
5177 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005178 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_LIST_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005179 "<list> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005180 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005181 }
5182 return (type);
5183}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005184
Daniel Veillard4255d502002-04-16 15:50:10 +00005185/**
5186 * xmlSchemaParseSimpleType:
5187 * @ctxt: a schema validation context
5188 * @schema: the schema being built
5189 * @node: a subtree containing XML Schema informations
5190 *
5191 * parse a XML schema Simple Type definition
5192 * *WARNING* this interface is highly subject to change
5193 *
William M. Bracke7091952004-05-11 15:09:58 +00005194 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005195 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005196 */
5197static xmlSchemaTypePtr
5198xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005199 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005200{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005201 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005203 const xmlChar *attrValue = NULL;
5204 xmlChar *repName = NULL;
5205 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005206
5207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5208 return (NULL);
5209
Daniel Veillardc0826a72004-08-10 14:17:33 +00005210 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005211
Daniel Veillardc0826a72004-08-10 14:17:33 +00005212 if (topLevel) {
5213 if (attr == NULL) {
5214 xmlSchemaPMissingAttrErr(ctxt,
5215 XML_SCHEMAP_S4S_ATTR_MISSING,
5216 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5217 "name", NULL);
5218 return (NULL);
5219 } else if (xmlSchemaPValAttrNode(ctxt,
5220 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5221 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005222 return (NULL);
5223 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005224 }
5225
5226 if (topLevel == 0) {
5227 char buf[100];
5228
Daniel Veillard01fa6152004-06-29 17:04:39 +00005229 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005230 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005231 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005232 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
5233 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL);
5234 if (type == NULL)
5235 return (NULL);
5236 type->node = node;
5237 type->type = XML_SCHEMA_TYPE_SIMPLE;
5238 /*
5239 * Check for illegal attributes.
5240 */
5241 attr = node->properties;
5242 while (attr != NULL) {
5243 if (attr->ns == NULL) {
5244 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5245 xmlSchemaPIllegalAttrErr(ctxt,
5246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5247 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005248 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005249 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5250 xmlSchemaPIllegalAttrErr(ctxt,
5251 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5252 &repName, type, attr);
5253 }
5254 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005255 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005256 } else {
5257 /*
5258 * Parse as global simple type definition.
5259 */
5260 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace);
5261 if (type == NULL)
5262 return (NULL);
5263 type->node = node;
5264 type->type = XML_SCHEMA_TYPE_SIMPLE;
5265 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5266 /*
5267 * Check for illegal attributes.
5268 */
5269 attr = node->properties;
5270 while (attr != NULL) {
5271 if (attr->ns == NULL) {
5272 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5273 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5274 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5275 xmlSchemaPIllegalAttrErr(ctxt,
5276 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5277 &repName, type, attr);
5278 }
5279 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5280 xmlSchemaPIllegalAttrErr(ctxt,
5281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5282 &repName, type, attr);
5283 }
5284 attr = attr->next;
5285 }
5286 /*
5287 * Attribute "final".
5288 */
5289 attr = xmlSchemaGetPropNode(node, "final");
5290 if (attr == NULL) {
5291 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5292 } else {
5293 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5294 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5295 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5296 XML_SCHEMAS_TYPE_FINAL_LIST,
5297 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5298
5299 xmlSchemaPSimpleTypeErr(ctxt,
5300 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5301 &repName, type, (xmlNodePtr) attr,
5302 XML_SCHEMAS_UNKNOWN, "(#all | List of (list | union | restriction)",
5303 attrValue, NULL, NULL, NULL);
5304 }
5305 }
5306 }
5307 /* TODO: Check id. */
5308 type->id = xmlSchemaGetProp(ctxt, node, "id");
5309 /*
5310 * And now for the children...
5311 */
5312 ctxtType = ctxt->ctxtType;
5313 ctxt->ctxtType = type;
5314 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005315 child = node->children;
5316 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005317 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5318 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005320 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005321 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005322 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005323 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005324 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005325 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005326 subtype = (xmlSchemaTypePtr)
5327 xmlSchemaParseList(ctxt, schema, child);
5328 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005329 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005330 subtype = (xmlSchemaTypePtr)
5331 xmlSchemaParseUnion(ctxt, schema, child);
5332 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005333 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 type->subtypes = subtype;
5335 if ((child != NULL) || (subtype == NULL)) {
5336 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5337 &repName, type, node, child, NULL,
5338 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005339 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005340 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 if (repName != NULL)
5342 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005343
Daniel Veillard4255d502002-04-16 15:50:10 +00005344 return (type);
5345}
5346
5347
5348/**
5349 * xmlSchemaParseGroup:
5350 * @ctxt: a schema validation context
5351 * @schema: the schema being built
5352 * @node: a subtree containing XML Schema informations
5353 *
5354 * parse a XML schema Group definition
5355 * *WARNING* this interface is highly subject to change
5356 *
William M. Bracke7091952004-05-11 15:09:58 +00005357 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005358 * 1 in case of success.
5359 */
5360static xmlSchemaTypePtr
5361xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005362 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005363{
5364 xmlSchemaTypePtr type, subtype;
5365 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005366 const xmlChar *name;
5367 const xmlChar *ref = NULL, *refNs = NULL;
5368 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00005369
5370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5371 return (NULL);
5372
5373
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005374 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005375 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5377 if (ref == NULL) {
5378 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005379 XML_SCHEMAP_GROUP_NONAME_NOREF,
5380 "Group definition or particle: One of the attributes \"name\" "
5381 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005382 return (NULL);
5383 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005384 if (refNs == NULL)
5385 refNs = schema->targetNamespace;
5386 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5387 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005388 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005389 type = xmlSchemaAddGroup(ctxt, schema, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005390 if (type == NULL)
5391 return (NULL);
5392 type->node = node;
5393 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005394 if (topLevel)
5395 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005396 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 type->ref = ref;
5398 type->refNs = refNs;
5399 type->minOccurs = xmlGetMinOccurs(ctxt, node);
5400 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
5401
5402 child = node->children;
5403 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005404 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5405 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005406 }
5407 subtype = NULL;
5408 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005409 subtype = (xmlSchemaTypePtr)
5410 xmlSchemaParseAll(ctxt, schema, child);
5411 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005412 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413 subtype = xmlSchemaParseChoice(ctxt, schema, child);
5414 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005416 subtype = (xmlSchemaTypePtr)
5417 xmlSchemaParseSequence(ctxt, schema, child);
5418 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 }
5420 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005421 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00005422 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005423 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005424 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005425 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005426 }
5427
5428 return (type);
5429}
5430
5431/**
5432 * xmlSchemaParseAll:
5433 * @ctxt: a schema validation context
5434 * @schema: the schema being built
5435 * @node: a subtree containing XML Schema informations
5436 *
5437 * parse a XML schema All definition
5438 * *WARNING* this interface is highly subject to change
5439 *
William M. Bracke7091952004-05-11 15:09:58 +00005440 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005441 * 1 in case of success.
5442 */
5443static xmlSchemaTypePtr
5444xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005446{
5447 xmlSchemaTypePtr type, subtype, last = NULL;
5448 xmlNodePtr child = NULL;
5449 xmlChar name[30];
5450
5451 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5452 return (NULL);
5453
5454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005455 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005456 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005457 if (type == NULL)
5458 return (NULL);
5459 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00005460 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005461 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005462 type->minOccurs = xmlGetMinOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005463 if (type->minOccurs > 1)
5464 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005465 "<all>: The value of the attribute \"minOccurs\" is invalid. "
5466 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005467 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
William M. Brackb15351e2003-12-27 04:34:42 +00005468 if (type->maxOccurs > 1)
5469 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 "<all>: The value of the attribute \"maxOccurs\" is invalid. "
5471 "Either \"0\" or \"1\" is expected.\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005472
5473 child = node->children;
5474 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005475 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5476 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005477 }
5478 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479 subtype = (xmlSchemaTypePtr)
5480 xmlSchemaParseElement(ctxt, schema, child, 0);
5481 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00005482 if (subtype->minOccurs > 1)
5483 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005484 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005485 NULL, NULL);
5486 if (subtype->maxOccurs > 1)
5487 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005488 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00005489 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 if (last == NULL) {
5491 type->subtypes = subtype;
5492 last = subtype;
5493 } else {
5494 last->next = subtype;
5495 last = subtype;
5496 }
5497 last->next = NULL;
5498 }
5499 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005500 }
5501 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005502 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005503 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005504 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005505 }
5506
5507 return (type);
5508}
5509
5510/**
Daniel Veillard1d913862003-11-21 00:28:39 +00005511 * xmlSchemaImportSchema
5512 *
5513 * @ctxt: a schema validation context
5514 * @schemaLocation: an URI defining where to find the imported schema
5515 *
5516 * import a XML schema
5517 * *WARNING* this interface is highly subject to change
5518 *
5519 * Returns -1 in case of error and 1 in case of success.
5520 */
5521static xmlSchemaImportPtr
5522xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
5523 const xmlChar *schemaLocation)
5524{
5525 xmlSchemaImportPtr import;
5526 xmlSchemaParserCtxtPtr newctxt;
5527
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005528 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
Daniel Veillard1d913862003-11-21 00:28:39 +00005529 if (newctxt == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005530 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
Daniel Veillard1d913862003-11-21 00:28:39 +00005531 NULL);
5532 return (NULL);
5533 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005534 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
5535 /* Keep the same dictionnary for parsing, really */
5536 xmlDictReference(ctxt->dict);
5537 newctxt->dict = ctxt->dict;
Daniel Veillardb0f397e2003-12-23 23:30:53 +00005538 newctxt->includes = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005539 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
5540
Daniel Veillard1d913862003-11-21 00:28:39 +00005541 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
5542 ctxt->userData);
5543
5544 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
5545 if (import == NULL) {
5546 xmlSchemaPErrMemory(NULL, "allocating imported schema",
5547 NULL);
5548 xmlSchemaFreeParserCtxt(newctxt);
5549 return (NULL);
5550 }
5551
5552 memset(import, 0, sizeof(xmlSchemaImport));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005553 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
Daniel Veillard1d913862003-11-21 00:28:39 +00005554 import->schema = xmlSchemaParse(newctxt);
5555
5556 if (import->schema == NULL) {
5557 /* FIXME use another error enum here ? */
5558 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005559 "Failed to import schema from location \"%s\".\n",
Daniel Veillard1d913862003-11-21 00:28:39 +00005560 schemaLocation, NULL);
5561
5562 xmlSchemaFreeParserCtxt(newctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 /* The schemaLocation is held by the dictionary.
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005564 if (import->schemaLocation != NULL)
5565 xmlFree((xmlChar *)import->schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005566 */
Daniel Veillard1d913862003-11-21 00:28:39 +00005567 xmlFree(import);
5568 return NULL;
5569 }
5570
5571 xmlSchemaFreeParserCtxt(newctxt);
5572 return import;
5573}
5574
5575
5576/**
Daniel Veillard5a872412002-05-22 06:40:27 +00005577 * xmlSchemaParseImport:
5578 * @ctxt: a schema validation context
5579 * @schema: the schema being built
5580 * @node: a subtree containing XML Schema informations
5581 *
5582 * parse a XML schema Import definition
5583 * *WARNING* this interface is highly subject to change
5584 *
William M. Bracke7091952004-05-11 15:09:58 +00005585 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard5a872412002-05-22 06:40:27 +00005586 * 1 in case of success.
5587 */
5588static int
5589xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005590 xmlNodePtr node)
Daniel Veillard5a872412002-05-22 06:40:27 +00005591{
5592 xmlNodePtr child = NULL;
Daniel Veillard1d913862003-11-21 00:28:39 +00005593 xmlSchemaImportPtr import = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005594 const xmlChar *namespace;
5595 const xmlChar *schemaLocation;
Daniel Veillard1d913862003-11-21 00:28:39 +00005596 const xmlChar *previous;
Daniel Veillard5a872412002-05-22 06:40:27 +00005597 xmlURIPtr check;
5598
Daniel Veillard1d913862003-11-21 00:28:39 +00005599
Daniel Veillard5a872412002-05-22 06:40:27 +00005600 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5601 return (-1);
5602
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005603 namespace = xmlSchemaGetProp(ctxt, node, "namespace");
Daniel Veillard5a872412002-05-22 06:40:27 +00005604 if (namespace != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005605 check = xmlParseURI((const char *) namespace);
5606 if (check == NULL) {
5607 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
5609 "Element <import>: The value \"%s\" of the attribute \"namespace\" is "
5610 "not a valid URI.\n",
5611 namespace, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005612 return (-1);
5613 } else {
5614 xmlFreeURI(check);
5615 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005616 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005617 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
Daniel Veillard5a872412002-05-22 06:40:27 +00005618 if (schemaLocation != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00005619 xmlChar *base = NULL;
5620 xmlChar *URI = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 check = xmlParseURI((const char *) schemaLocation);
5622 if (check == NULL) {
5623 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005624 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
5625 "Element <import>: The value \"%s\" of the attribute \"schemaLocation\" is "
5626 "not a valid URI.\n",
5627 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005628 return (-1);
5629 } else {
5630 xmlFreeURI(check);
5631 }
Daniel Veillard1d913862003-11-21 00:28:39 +00005632 base = xmlNodeGetBase(node->doc, node);
5633 if (base == NULL) {
5634 URI = xmlBuildURI(schemaLocation, node->doc->URL);
5635 } else {
5636 URI = xmlBuildURI(schemaLocation, base);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005637 xmlFree(base);
Daniel Veillard1d913862003-11-21 00:28:39 +00005638 }
Daniel Veillard1d913862003-11-21 00:28:39 +00005639 if (URI != NULL) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005640 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
5641 xmlFree(URI);
Daniel Veillard1d913862003-11-21 00:28:39 +00005642 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005643 }
5644 if (schema->schemasImports == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645 schema->schemasImports = xmlHashCreate(10);
5646 if (schema->schemasImports == NULL) {
5647 xmlSchemaPErr2(ctxt, node, child,
5648 XML_SCHEMAP_FAILED_BUILD_IMPORT,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005649 "Internal error: failed to build import table.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005650 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005651 return (-1);
5652 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005653 }
5654 if (namespace == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00005655 import = xmlHashLookup(schema->schemasImports,
5656 XML_SCHEMAS_DEFAULT_NAMESPACE);
5657 if (import != NULL)
5658 previous = import->schemaLocation;
5659 else
5660 previous = NULL;
5661
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 if (schemaLocation != NULL) {
5663 if (previous != NULL) {
5664 if (!xmlStrEqual(schemaLocation, previous)) {
5665 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005666 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
5667 "<import>: Redefining import for default namespace "
5668 "with a different URI: \"%s\".\n",
5669 schemaLocation, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005670 }
5671 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00005672 import = xmlSchemaImportSchema(ctxt, schemaLocation);
5673 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00005674 return (-1);
5675 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005676 xmlHashAddEntry(schema->schemasImports,
5677 XML_SCHEMAS_DEFAULT_NAMESPACE,
Daniel Veillard1d913862003-11-21 00:28:39 +00005678 import);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005679 }
5680 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005681 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00005682 import = xmlHashLookup(schema->schemasImports, namespace);
5683 if (import != NULL)
5684 previous = import->schemaLocation;
5685 else
5686 previous = NULL;
5687
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005688 if (schemaLocation != NULL) {
5689 if (previous != NULL) {
5690 if (!xmlStrEqual(schemaLocation, previous)) {
5691 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005692 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,
5693 "<import>: Redefining import for namespace \"%s\" with "
5694 "a different URI: \"%s\".\n",
5695 namespace, schemaLocation);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 }
5697 } else {
Daniel Veillard1d913862003-11-21 00:28:39 +00005698 import = xmlSchemaImportSchema(ctxt, schemaLocation);
5699 if (import == NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00005700 return (-1);
5701 }
Daniel Veillard3646d642004-06-02 19:19:14 +00005702 if (!xmlStrEqual(import->schema->targetNamespace, namespace)) {
5703 if (namespace == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704
Daniel Veillard3646d642004-06-02 19:19:14 +00005705 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00005706 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005707 "<import>: No \"namespace\" attribute was "
5708 "specified, thus the imported schema document "
5709 "must have no target namespace.\n",
5710 NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005711 }
5712 } else {
5713 if (import->schema->targetNamespace != NULL) {
William M. Brack767265d2004-06-03 10:50:29 +00005714 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005715 "<import>: The value \"%s\" of the attribute "
5716 "\"namespace\" is not identical to the "
5717 "target namespace \"%s\" of the "
5718 "imported schema document.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00005719 namespace, import->schema->targetNamespace);
5720 } else {
William M. Brack767265d2004-06-03 10:50:29 +00005721 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_SRC_IMPORT_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 "<import>: The attribute \"namespace\", requires "
5723 "the imported schema document to have a target "
5724 "namespace of \"%s\".\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00005725 namespace, NULL);
5726 }
5727 }
5728 xmlSchemaFreeImport(import);
5729 return (-1);
5730 }
5731
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005732 xmlHashAddEntry(schema->schemasImports,
Daniel Veillard1d913862003-11-21 00:28:39 +00005733 namespace, import);
Daniel Veillard3646d642004-06-02 19:19:14 +00005734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005735 }
5736 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005737 }
Daniel Veillard5a872412002-05-22 06:40:27 +00005738
5739 child = node->children;
5740 while (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 /*
5742 * the annotations here are simply discarded ...
5743 */
5744 child = child->next;
Daniel Veillard5a872412002-05-22 06:40:27 +00005745 }
5746 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005747 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005748 "<import> has unexpected content.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005749 return (-1);
Daniel Veillard5a872412002-05-22 06:40:27 +00005750 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005751 return (1);
Daniel Veillard5a872412002-05-22 06:40:27 +00005752}
5753
5754/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005755 * xmlSchemaCleanupDoc:
5756 * @ctxt: a schema validation context
5757 * @node: the root of the document.
5758 *
5759 * removes unwanted nodes in a schemas document tree
5760 */
5761static void
5762xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
5763{
5764 xmlNodePtr delete, cur;
5765
5766 if ((ctxt == NULL) || (root == NULL)) return;
5767
5768 /*
5769 * Remove all the blank text nodes
5770 */
5771 delete = NULL;
5772 cur = root;
5773 while (cur != NULL) {
5774 if (delete != NULL) {
5775 xmlUnlinkNode(delete);
5776 xmlFreeNode(delete);
5777 delete = NULL;
5778 }
5779 if (cur->type == XML_TEXT_NODE) {
5780 if (IS_BLANK_NODE(cur)) {
5781 if (xmlNodeGetSpacePreserve(cur) != 1) {
5782 delete = cur;
5783 }
5784 }
5785 } else if ((cur->type != XML_ELEMENT_NODE) &&
5786 (cur->type != XML_CDATA_SECTION_NODE)) {
5787 delete = cur;
5788 goto skip_children;
5789 }
5790
5791 /*
5792 * Skip to next node
5793 */
5794 if (cur->children != NULL) {
5795 if ((cur->children->type != XML_ENTITY_DECL) &&
5796 (cur->children->type != XML_ENTITY_REF_NODE) &&
5797 (cur->children->type != XML_ENTITY_NODE)) {
5798 cur = cur->children;
5799 continue;
5800 }
5801 }
5802 skip_children:
5803 if (cur->next != NULL) {
5804 cur = cur->next;
5805 continue;
5806 }
5807
5808 do {
5809 cur = cur->parent;
5810 if (cur == NULL)
5811 break;
5812 if (cur == root) {
5813 cur = NULL;
5814 break;
5815 }
5816 if (cur->next != NULL) {
5817 cur = cur->next;
5818 break;
5819 }
5820 } while (cur != NULL);
5821 }
5822 if (delete != NULL) {
5823 xmlUnlinkNode(delete);
5824 xmlFreeNode(delete);
5825 delete = NULL;
5826 }
5827}
5828
5829/**
5830 * xmlSchemaParseSchemaTopLevel:
5831 * @ctxt: a schema validation context
5832 * @schema: the schemas
5833 * @nodes: the list of top level nodes
5834 *
5835 * Returns the internal XML Schema structure built from the resource or
5836 * NULL in case of error
5837 */
5838static void
5839xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
5840 xmlSchemaPtr schema, xmlNodePtr nodes)
5841{
5842 xmlNodePtr child;
5843 xmlSchemaAnnotPtr annot;
5844
5845 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
5846 return;
5847
5848 child = nodes;
5849 while ((IS_SCHEMA(child, "include")) ||
5850 (IS_SCHEMA(child, "import")) ||
5851 (IS_SCHEMA(child, "redefine")) ||
5852 (IS_SCHEMA(child, "annotation"))) {
5853 if (IS_SCHEMA(child, "annotation")) {
5854 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5855 if (schema->annot == NULL)
5856 schema->annot = annot;
5857 else
5858 xmlSchemaFreeAnnot(annot);
5859 } else if (IS_SCHEMA(child, "import")) {
5860 xmlSchemaParseImport(ctxt, schema, child);
5861 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00005862 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005863 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00005864 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005865 } else if (IS_SCHEMA(child, "redefine")) {
5866 TODO
5867 }
5868 child = child->next;
5869 }
5870 while (child != NULL) {
5871 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005872 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005873 child = child->next;
5874 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005875 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005876 child = child->next;
5877 } else if (IS_SCHEMA(child, "element")) {
5878 xmlSchemaParseElement(ctxt, schema, child, 1);
5879 child = child->next;
5880 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005881 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005882 child = child->next;
5883 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005884 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005885 child = child->next;
5886 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005887 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005888 child = child->next;
5889 } else if (IS_SCHEMA(child, "notation")) {
5890 xmlSchemaParseNotation(ctxt, schema, child);
5891 child = child->next;
5892 } else {
5893 xmlSchemaPErr2(ctxt, NULL, child,
5894 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005896 child->name, NULL);
5897 child = child->next;
5898 }
5899 while (IS_SCHEMA(child, "annotation")) {
5900 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5901 if (schema->annot == NULL)
5902 schema->annot = annot;
5903 else
5904 xmlSchemaFreeAnnot(annot);
5905 child = child->next;
5906 }
5907 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005908 ctxt->parentItem = NULL;
5909 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005910}
5911
5912/**
5913 * xmlSchemaParseInclude:
5914 * @ctxt: a schema validation context
5915 * @schema: the schema being built
5916 * @node: a subtree containing XML Schema informations
5917 *
5918 * parse a XML schema Include definition
5919 *
William M. Bracke7091952004-05-11 15:09:58 +00005920 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005921 * 1 in case of success.
5922 */
5923static int
5924xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5925 xmlNodePtr node)
5926{
5927 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005929 xmlURIPtr check;
5930 xmlDocPtr doc;
5931 xmlNodePtr root;
5932 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 int wasConvertingNs = 0;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005934
5935
5936 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5937 return (-1);
5938
5939 /*
5940 * Preliminary step, extract the URI-Reference for the include and
5941 * make an URI from the base.
5942 */
5943 schemaLocation = xmlSchemaGetProp(ctxt, node, "schemaLocation");
5944 if (schemaLocation != NULL) {
5945 xmlChar *base = NULL;
5946 xmlChar *URI = NULL;
5947 check = xmlParseURI((const char *) schemaLocation);
5948 if (check == NULL) {
5949 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005950 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,
5951 "<include>: The value \"%s\" of the attribute "
5952 "\"schemaLocation\" is not a valid URI.\n",
5953 schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005954 return (-1);
5955 } else {
5956 xmlFreeURI(check);
5957 }
5958 base = xmlNodeGetBase(node->doc, node);
5959 if (base == NULL) {
5960 URI = xmlBuildURI(schemaLocation, node->doc->URL);
5961 } else {
5962 URI = xmlBuildURI(schemaLocation, base);
5963 xmlFree(base);
5964 }
5965 if (URI != NULL) {
5966 schemaLocation = xmlDictLookup(ctxt->dict, URI, -1);
5967 xmlFree(URI);
5968 }
5969 } else {
5970 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005971 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
5972 "<include>: The attribute \"schemaLocation\" is missing.\n",
5973 NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005974 return (-1);
5975 }
5976
5977 child = node->children;
5978 while (IS_SCHEMA(child, "annotation")) {
5979 /*
5980 * the annotations here are simply discarded ...
5981 */
5982 child = child->next;
5983 }
5984 if (child != NULL) {
5985 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005986 "<include> has unexpected content.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005987 return (-1);
5988 }
5989
5990 /*
5991 * First step is to parse the input document into an DOM/Infoset
5992 */
5993 doc = xmlReadFile((const char *) schemaLocation, NULL,
5994 SCHEMAS_PARSE_OPTIONS);
5995 if (doc == NULL) {
5996 xmlSchemaPErr(ctxt, NULL,
5997 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005998 "<include>: failed to load the document \"%s\".\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00005999 ctxt->URL, NULL);
6000 return(-1);
6001 }
6002
6003 /*
6004 * Then extract the root of the schema
6005 */
6006 root = xmlDocGetRootElement(doc);
6007 if (root == NULL) {
6008 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006009 XML_SCHEMAP_NOROOT,
6010 "<include>: The included document \"%s\" has no document "
6011 "element.\n", schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006012 xmlFreeDoc(doc);
6013 return (-1);
6014 }
6015
6016 /*
6017 * Remove all the blank text nodes
6018 */
6019 xmlSchemaCleanupDoc(ctxt, root);
6020
6021 /*
6022 * Check the schemas top level element
6023 */
6024 if (!IS_SCHEMA(root, "schema")) {
6025 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006026 XML_SCHEMAP_NOT_SCHEMA,
6027 "<include>: The document \"%s\" is not a schema document.\n",
6028 schemaLocation, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006029 xmlFreeDoc(doc);
6030 return (-1);
6031 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006032
6033 targetNamespace = xmlSchemaGetProp(ctxt, node, "targetNamespace");
6034 /*
6035 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6036 * value· is identical to the ·actual value· of the targetNamespace
6037 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6038 */
6039 if (targetNamespace != NULL) {
6040 if (schema->targetNamespace == NULL) {
6041 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6042 XML_SCHEMAP_SRC_INCLUDE,
6043 "<include>: The target namespace of the included schema "
6044 "\"%s\" has to be absent, since the including schema "
6045 "has no target namespace.\n",
6046 schemaLocation, NULL);
6047 xmlFreeDoc(doc);
6048 return (-1);
6049 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6050 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6051 XML_SCHEMAP_SRC_INCLUDE,
6052 "<include>: The target namespace \"%s\" of the included "
6053 "schema \"%s\" is different from \"%s\" of the including "
6054 "schema.\n",
6055 schemaLocation, NULL);
6056 xmlFreeDoc(doc);
6057 return (-1);
6058 }
6059 } else if (schema->targetNamespace != NULL) {
6060 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
6061 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
6062 } else
6063 wasConvertingNs = 1;
6064 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006065 /*
6066 * register the include
6067 */
6068 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
6069 if (include == NULL) {
6070 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
6071 xmlFreeDoc(doc);
6072 return (-1);
6073 }
6074
6075 memset(include, 0, sizeof(xmlSchemaInclude));
6076 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6077 include->doc = doc;
6078 include->next = schema->includes;
6079 schema->includes = include;
6080
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006081 /*
6082 * parse the declarations in the included file like if they
6083 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006084 */
6085 /*
6086 * TODO FIXME URGENT: The validation of the <schema> element is not done here.
6087 * Additionally the default values (e.g. "blockDefault", "elementFormDefault")
6088 * are not set. We need to store the current values here, set them to the
6089 * values of the included schema and recover the old ones afterwards.
6090 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006091 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006092 /*
6093 * Remove the converting flag.
6094 */
6095 if (wasConvertingNs == 0)
6096 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006097 return (1);
6098}
6099
6100/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 * xmlSchemaParseChoice:
6102 * @ctxt: a schema validation context
6103 * @schema: the schema being built
6104 * @node: a subtree containing XML Schema informations
6105 *
6106 * parse a XML schema Choice definition
6107 * *WARNING* this interface is highly subject to change
6108 *
William M. Bracke7091952004-05-11 15:09:58 +00006109 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 * 1 in case of success.
6111 */
6112static xmlSchemaTypePtr
6113xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006114 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006115{
6116 xmlSchemaTypePtr type, subtype, last = NULL;
6117 xmlNodePtr child = NULL;
6118 xmlChar name[30];
6119
6120 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6121 return (NULL);
6122
6123
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006124 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006125 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006126 if (type == NULL)
6127 return (NULL);
6128 type->node = node;
6129 type->type = XML_SCHEMA_TYPE_CHOICE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006130 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006131 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6132 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
6133
6134 child = node->children;
6135 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6137 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 }
6139 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 (IS_SCHEMA(child, "group")) ||
6141 (IS_SCHEMA(child, "any")) ||
6142 (IS_SCHEMA(child, "choice")) ||
6143 (IS_SCHEMA(child, "sequence"))) {
6144 subtype = NULL;
6145 if (IS_SCHEMA(child, "element")) {
6146 subtype = (xmlSchemaTypePtr)
6147 xmlSchemaParseElement(ctxt, schema, child, 0);
6148 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006149 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006150 } else if (IS_SCHEMA(child, "any")) {
6151 subtype = xmlSchemaParseAny(ctxt, schema, child);
6152 } else if (IS_SCHEMA(child, "sequence")) {
6153 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6154 } else if (IS_SCHEMA(child, "choice")) {
6155 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6156 }
6157 if (subtype != NULL) {
6158 if (last == NULL) {
6159 type->subtypes = subtype;
6160 last = subtype;
6161 } else {
6162 last->next = subtype;
6163 last = subtype;
6164 }
6165 last->next = NULL;
6166 }
6167 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006168 }
6169 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006170 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006171 "<choice> has unexpected content.\n",
6172 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006173 }
6174
6175 return (type);
6176}
6177
6178/**
6179 * xmlSchemaParseSequence:
6180 * @ctxt: a schema validation context
6181 * @schema: the schema being built
6182 * @node: a subtree containing XML Schema informations
6183 *
6184 * parse a XML schema Sequence definition
6185 * *WARNING* this interface is highly subject to change
6186 *
William M. Bracke7091952004-05-11 15:09:58 +00006187 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 * 1 in case of success.
6189 */
6190static xmlSchemaTypePtr
6191xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006192 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006193{
6194 xmlSchemaTypePtr type, subtype, last = NULL;
6195 xmlNodePtr child = NULL;
6196 xmlChar name[30];
6197
6198 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6199 return (NULL);
6200
6201
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006202 snprintf((char *) name, 30, "sequence %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006203 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006204 if (type == NULL)
6205 return (NULL);
6206 type->node = node;
6207 type->type = XML_SCHEMA_TYPE_SEQUENCE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006208 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006209 type->minOccurs = xmlGetMinOccurs(ctxt, node);
6210 type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
6211
6212 child = node->children;
6213 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006214 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6215 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006216 }
6217 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006218 (IS_SCHEMA(child, "group")) ||
6219 (IS_SCHEMA(child, "any")) ||
6220 (IS_SCHEMA(child, "choice")) ||
6221 (IS_SCHEMA(child, "sequence"))) {
6222 subtype = NULL;
6223 if (IS_SCHEMA(child, "element")) {
6224 subtype = (xmlSchemaTypePtr)
6225 xmlSchemaParseElement(ctxt, schema, child, 0);
6226 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006227 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006228 } else if (IS_SCHEMA(child, "any")) {
6229 subtype = xmlSchemaParseAny(ctxt, schema, child);
6230 } else if (IS_SCHEMA(child, "choice")) {
6231 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6232 } else if (IS_SCHEMA(child, "sequence")) {
6233 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6234 }
6235 if (subtype != NULL) {
6236 if (last == NULL) {
6237 type->subtypes = subtype;
6238 last = subtype;
6239 } else {
6240 last->next = subtype;
6241 last = subtype;
6242 }
6243 last->next = NULL;
6244 }
6245 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006246 }
6247 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006248 xmlSchemaPErr2(ctxt, node, child,
6249 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006250 "<sequence> has unexpected content.\n",
6251 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006252 }
6253
6254 return (type);
6255}
6256
6257/**
6258 * xmlSchemaParseRestriction:
6259 * @ctxt: a schema validation context
6260 * @schema: the schema being built
6261 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00006262 *
6263 * parse a XML schema Restriction definition
6264 * *WARNING* this interface is highly subject to change
6265 *
6266 * Returns the type definition or NULL in case of error
6267 */
6268static xmlSchemaTypePtr
6269xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006270 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006271{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006272 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006273 xmlNodePtr child = NULL;
6274 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006275 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006276
6277 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6278 return (NULL);
6279
6280 oldcontainer = ctxt->container;
6281
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006282 snprintf((char *) name, 30, "restriction %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006283 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006284 if (type == NULL)
6285 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006286 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006287 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006288 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006289 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00006290 if ((type->base == NULL) &&
6291 (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006292 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillard01fa6152004-06-29 17:04:39 +00006293 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006294 "<restriction>: The attribute \"base\" is missing.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00006295 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006296 }
6297 ctxt->container = name;
6298
6299 child = node->children;
6300 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6302 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006303 }
6304 subtype = NULL;
6305
Daniel Veillard01fa6152004-06-29 17:04:39 +00006306 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
6307 if (IS_SCHEMA(child, "all")) {
6308 subtype = (xmlSchemaTypePtr)
6309 xmlSchemaParseAll(ctxt, schema, child);
6310 child = child->next;
6311 type->subtypes = subtype;
6312 } else if (IS_SCHEMA(child, "choice")) {
6313 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6314 child = child->next;
6315 type->subtypes = subtype;
6316 } else if (IS_SCHEMA(child, "sequence")) {
6317 subtype = (xmlSchemaTypePtr)
6318 xmlSchemaParseSequence(ctxt, schema, child);
6319 child = child->next;
6320 type->subtypes = subtype;
6321 } else if (IS_SCHEMA(child, "group")) {
6322 subtype = (xmlSchemaTypePtr)
6323 xmlSchemaParseGroup(ctxt, schema, child, 0);
6324 child = child->next;
6325 type->subtypes = subtype;
6326 }
6327 } else if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
6328 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
6329 xmlSchemaFacetPtr facet, lastfacet = NULL;
6330
6331 if (IS_SCHEMA(child, "simpleType")) {
6332 subtype = (xmlSchemaTypePtr)
6333 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6334 /*
6335 * For the simple type this serves as the base type.
6336 */
6337 type->baseType = subtype;
6338 /*
6339 * For the complex type this serves as information for the
6340 * definition of the content type.
6341 * Additionally this is a hack for the simple type, to save
6342 * the information that a local simple type was defined; thus
6343 * allowing to check: src-restriction-base-or-simpleType.
6344 */
6345 type->subtypes = subtype;
6346 child = child->next;
6347 }
6348 /*
6349 * Add the facets to the parent simpleType/complexType.
6350 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351 /*
6352 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
6353 * Simple Type Definition Schema Representation Constraint:
6354 * *Single Facet Value*
6355 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006356 while ((IS_SCHEMA(child, "minInclusive")) ||
6357 (IS_SCHEMA(child, "minExclusive")) ||
6358 (IS_SCHEMA(child, "maxInclusive")) ||
6359 (IS_SCHEMA(child, "maxExclusive")) ||
6360 (IS_SCHEMA(child, "totalDigits")) ||
6361 (IS_SCHEMA(child, "fractionDigits")) ||
6362 (IS_SCHEMA(child, "pattern")) ||
6363 (IS_SCHEMA(child, "enumeration")) ||
6364 (IS_SCHEMA(child, "whiteSpace")) ||
6365 (IS_SCHEMA(child, "length")) ||
6366 (IS_SCHEMA(child, "maxLength")) ||
6367 (IS_SCHEMA(child, "minLength"))) {
6368 facet = xmlSchemaParseFacet(ctxt, schema, child);
6369 if (facet != NULL) {
6370 if (lastfacet == NULL)
6371 ctxt->ctxtType->facets = facet;
6372 else
6373 lastfacet->next = facet;
6374 lastfacet = facet;
6375 lastfacet->next = NULL;
6376 }
6377 child = child->next;
6378 }
6379 /*
6380 * Create links for derivation and validation.
6381 */
6382 if (lastfacet != NULL) {
6383 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
6384
6385 facet = ctxt->ctxtType->facets;
6386 do {
6387 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
6388 if (facetLink == NULL) {
6389 xmlSchemaPErrMemory(ctxt, "allocation a facet link", NULL);
6390 xmlFree(facetLink);
6391 return (NULL);
6392 }
6393 facetLink->facet = facet;
6394 facetLink->next = NULL;
6395 if (lastFacetLink == NULL)
6396 ctxt->ctxtType->facetSet = facetLink;
6397 else
6398 lastFacetLink->next = facetLink;
6399 lastFacetLink = facetLink;
6400 facet = facet->next;
6401 } while (facet != NULL);
6402 }
6403 }
6404 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)
6405 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00006406 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006407 xmlSchemaPErr2(ctxt, node, child,
6408 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006409 "<restriction> has unexpected content.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00006410 type->name, NULL);
6411 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006412 ctxt->container = oldcontainer;
6413 return (type);
6414}
6415
6416/**
6417 * xmlSchemaParseExtension:
6418 * @ctxt: a schema validation context
6419 * @schema: the schema being built
6420 * @node: a subtree containing XML Schema informations
6421 *
6422 * parse a XML schema Extension definition
6423 * *WARNING* this interface is highly subject to change
6424 *
6425 * Returns the type definition or NULL in case of error
6426 */
6427static xmlSchemaTypePtr
6428xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006429 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006430{
6431 xmlSchemaTypePtr type, subtype;
6432 xmlNodePtr child = NULL;
6433 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006434 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006435
6436 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6437 return (NULL);
6438
6439 oldcontainer = ctxt->container;
6440
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006441 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006442 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006443 if (type == NULL)
6444 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006445 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006446 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006447 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006448 ctxt->container = name;
6449
6450 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
6451 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006452 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006453 "<extension>: The attribute \"base\" is missing.\n",
6454 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006455 }
6456 child = node->children;
6457 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006458 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6459 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006460 }
6461 subtype = NULL;
6462
6463 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006464 subtype = xmlSchemaParseAll(ctxt, schema, child);
6465 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006466 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006467 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6468 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006469 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006470 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6471 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006472 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006473 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006474 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006475 }
6476 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006477 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006478 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
6479 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006480 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
6482 "<extension> has unexpected content.\n", type->name,
6483 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006484 }
6485 ctxt->container = oldcontainer;
6486 return (type);
6487}
6488
6489/**
6490 * xmlSchemaParseSimpleContent:
6491 * @ctxt: a schema validation context
6492 * @schema: the schema being built
6493 * @node: a subtree containing XML Schema informations
6494 *
6495 * parse a XML schema SimpleContent definition
6496 * *WARNING* this interface is highly subject to change
6497 *
6498 * Returns the type definition or NULL in case of error
6499 */
6500static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006501xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
6502 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006503{
6504 xmlSchemaTypePtr type, subtype;
6505 xmlNodePtr child = NULL;
6506 xmlChar name[30];
6507
6508 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6509 return (NULL);
6510
William M. Bracke7091952004-05-11 15:09:58 +00006511 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006512 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006513 if (type == NULL)
6514 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006515 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00006516 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006517 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006518
6519 child = node->children;
6520 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006521 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6522 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006523 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006524 ctxt->parentItem = type;
6525 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006527 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006528 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006529 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006530 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006531 subtype = (xmlSchemaTypePtr)
6532 xmlSchemaParseExtension(ctxt, schema, child);
6533 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006534 }
6535 type->subtypes = subtype;
6536 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006537 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
6539 "<simpleContent> has unexpected content.\n",
6540 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006541 }
6542 return (type);
6543}
6544
6545/**
6546 * xmlSchemaParseComplexContent:
6547 * @ctxt: a schema validation context
6548 * @schema: the schema being built
6549 * @node: a subtree containing XML Schema informations
6550 *
6551 * parse a XML schema ComplexContent definition
6552 * *WARNING* this interface is highly subject to change
6553 *
6554 * Returns the type definition or NULL in case of error
6555 */
6556static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006557xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
6558 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006559{
6560 xmlSchemaTypePtr type, subtype;
6561 xmlNodePtr child = NULL;
6562 xmlChar name[30];
6563
6564 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6565 return (NULL);
6566
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006567 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006568 type = xmlSchemaAddType(ctxt, schema, name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006569 if (type == NULL)
6570 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006571 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006572 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006573 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006574
6575 child = node->children;
6576 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006577 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6578 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006579 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006580 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006581 subtype = NULL;
6582 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006583 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006584 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006585 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006586 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006587 subtype = (xmlSchemaTypePtr)
6588 xmlSchemaParseExtension(ctxt, schema, child);
6589 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 }
6591 type->subtypes = subtype;
6592 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006593 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006594 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
6595 "<complexContent> has unexpected content.\n",
6596 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006597 }
6598 return (type);
6599}
6600
6601/**
6602 * xmlSchemaParseComplexType:
6603 * @ctxt: a schema validation context
6604 * @schema: the schema being built
6605 * @node: a subtree containing XML Schema informations
6606 *
6607 * parse a XML schema Complex Type definition
6608 * *WARNING* this interface is highly subject to change
6609 *
6610 * Returns the type definition or NULL in case of error
6611 */
6612static xmlSchemaTypePtr
6613xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006614 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006615{
Daniel Veillard01fa6152004-06-29 17:04:39 +00006616 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006618 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00006619 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006620 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00006621
6622 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6623 return (NULL);
6624
Daniel Veillard01fa6152004-06-29 17:04:39 +00006625 ctxtType = ctxt->ctxtType;
6626
Daniel Veillard4255d502002-04-16 15:50:10 +00006627 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006628 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006629 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00006630 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006631 name = (const xmlChar *)buf;
6632 type = xmlSchemaAddType(ctxt, schema, name, NULL);
6633 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006634
William M. Bracke7091952004-05-11 15:09:58 +00006635 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
6636 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00006637 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006639 return (NULL);
6640 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006641 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00006642 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00006643
Daniel Veillard4255d502002-04-16 15:50:10 +00006644 type->node = node;
6645 type->type = XML_SCHEMA_TYPE_COMPLEX;
Daniel Veillard3646d642004-06-02 19:19:14 +00006646 if (topLevel)
6647 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006648 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 ctxt->container = name;
6650
6651 child = node->children;
6652 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006653 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006655 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006656 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006657 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00006658 /* 3.4.3 : 2.2
6659 * Specifying mixed='true' when the <simpleContent>
6660 * alternative is chosen has no effect
6661 */
6662 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
6663 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006664 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
6665 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006666 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006667 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
6668 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006669 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006670 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006671
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006672 if (IS_SCHEMA(child, "all")) {
6673 subtype = xmlSchemaParseAll(ctxt, schema, child);
6674 child = child->next;
6675 } else if (IS_SCHEMA(child, "choice")) {
6676 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6677 child = child->next;
6678 } else if (IS_SCHEMA(child, "sequence")) {
6679 subtype = xmlSchemaParseSequence(ctxt, schema, child);
6680 child = child->next;
6681 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006682 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006683 child = child->next;
6684 }
6685 if (subtype != NULL)
6686 type->subtypes = subtype;
6687 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Daniel Veillard4255d502002-04-16 15:50:10 +00006688 }
6689 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006690 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006691 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
6692 "Complex type definition \"%s\" has unexpected content.\n",
6693 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 }
Daniel Veillard3646d642004-06-02 19:19:14 +00006695 if (type->attributeWildcard != NULL)
6696 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006698 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00006699 return (type);
6700}
6701
Daniel Veillard4255d502002-04-16 15:50:10 +00006702/**
6703 * xmlSchemaParseSchema:
6704 * @ctxt: a schema validation context
6705 * @node: a subtree containing XML Schema informations
6706 *
6707 * parse a XML schema definition from a node set
6708 * *WARNING* this interface is highly subject to change
6709 *
6710 * Returns the internal XML Schema structure built from the resource or
6711 * NULL in case of error
6712 */
6713static xmlSchemaPtr
6714xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
6715{
6716 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006717 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006718 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006719 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006720
6721 if ((ctxt == NULL) || (node == NULL))
6722 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006723
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006724 nberrors = ctxt->nberrors;
6725 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006726 if (IS_SCHEMA(node, "schema")) {
6727 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006728 if (schema == NULL)
6729 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006730 attr = xmlSchemaGetPropNode(node, "targetNamespace");
6731 if (attr != NULL) {
6732 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6733 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
6734 /*
6735 * TODO: Should we proceed with an invalid target namespace?
6736 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006737 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
6738 } else {
6739 schema->targetNamespace = NULL;
6740 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006742 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006743 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
6744 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
6745
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006746 val = xmlSchemaGetProp(ctxt, node, "elementFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006747 if (val != NULL) {
6748 if (xmlStrEqual(val, BAD_CAST "qualified"))
6749 schema->flags |= XML_SCHEMAS_QUALIF_ELEM;
6750 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006751 xmlSchemaPErr(ctxt, node,
6752 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6753 "Element \"schema\": The value \"%s\" of the attribute "
6754 "\"elementFormDefault\" is not valid. Expected is "
6755 "(qualified | unqualified).\n",
6756 val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006757 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006758 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006759 /* Removed, since the default value for elementFormDefault
6760 * is "unqualified".
6761 */
6762 /* schema->flags |= XML_SCHEMAS_QUALIF_ELEM; */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006763 }
6764 val = xmlSchemaGetProp(ctxt, node, "attributeFormDefault");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006765 if (val != NULL) {
6766 if (xmlStrEqual(val, BAD_CAST "qualified"))
6767 schema->flags |= XML_SCHEMAS_QUALIF_ATTR;
6768 else if (!xmlStrEqual(val, BAD_CAST "unqualified")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006769 xmlSchemaPErr(ctxt, node,
6770 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6771 "Element \"schema\": The value \"%s\" of the attribute "
6772 "\"attributeFormDefault\" is not valid. Expected is "
6773 "(qualified | unqualified).\n",
6774 val, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006775 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006776 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006777
Daniel Veillard01fa6152004-06-29 17:04:39 +00006778 val = xmlSchemaGetProp(ctxt, node, "finalDefault");
6779 if (val != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6781 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6782 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6783 -1,
6784 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6785 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6786 xmlSchemaPErr(ctxt, node,
6787 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6788 "Element \"schema\": The value \"%s\" of the attribute "
6789 "\"finalDefault\" is not valid. Expected is "
6790 "(#all | List of (extension | restriction | list | "
6791 "union)).\n",
6792 val, NULL);
6793 }
6794 }
6795
6796 val = xmlSchemaGetProp(ctxt, node, "blockDefault");
6797 if (val != NULL) {
6798 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6799 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6800 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6801 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6802 xmlSchemaPErr(ctxt, node,
6803 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6804 "Element \"schema\": The value \"%s\" of the attribute "
6805 "\"blockDefault\" is not valid. Expected is "
6806 "(#all | List of (extension | restriction | "
6807 "substitution)).\n",
6808 val, NULL);
6809 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006810 }
6811
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006812 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
6813 } else {
6814 xmlDocPtr doc;
6815
6816 doc = node->doc;
6817
6818 if ((doc != NULL) && (doc->URL != NULL)) {
6819 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6820 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006822 } else {
6823 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
6824 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006825 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006826 }
6827 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006828 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006829 if (ctxt->nberrors != 0) {
6830 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006831 xmlSchemaFree(schema);
6832 schema = NULL;
6833 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00006834 }
6835 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00006836#ifdef DEBUG
6837 if (schema == NULL)
6838 xmlGenericError(xmlGenericErrorContext,
6839 "xmlSchemaParse() failed\n");
6840#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00006841 return (schema);
6842}
6843
6844/************************************************************************
6845 * *
6846 * Validating using Schemas *
6847 * *
6848 ************************************************************************/
6849
6850/************************************************************************
6851 * *
6852 * Reading/Writing Schemas *
6853 * *
6854 ************************************************************************/
6855
6856/**
6857 * xmlSchemaNewParserCtxt:
6858 * @URL: the location of the schema
6859 *
6860 * Create an XML Schemas parse context for that file/resource expected
6861 * to contain an XML Schemas file.
6862 *
6863 * Returns the parser context or NULL in case of error
6864 */
6865xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006866xmlSchemaNewParserCtxt(const char *URL)
6867{
Daniel Veillard4255d502002-04-16 15:50:10 +00006868 xmlSchemaParserCtxtPtr ret;
6869
6870 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006871 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006872
6873 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6874 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006875 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006876 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006877 return (NULL);
6878 }
6879 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006880 ret->dict = xmlDictCreate();
6881 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006882 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00006883 return (ret);
6884}
6885
6886/**
Daniel Veillard6045c902002-10-09 21:13:59 +00006887 * xmlSchemaNewMemParserCtxt:
6888 * @buffer: a pointer to a char array containing the schemas
6889 * @size: the size of the array
6890 *
6891 * Create an XML Schemas parse context for that memory buffer expected
6892 * to contain an XML Schemas file.
6893 *
6894 * Returns the parser context or NULL in case of error
6895 */
6896xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006897xmlSchemaNewMemParserCtxt(const char *buffer, int size)
6898{
Daniel Veillard6045c902002-10-09 21:13:59 +00006899 xmlSchemaParserCtxtPtr ret;
6900
6901 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006902 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00006903
6904 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6905 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006907 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00006908 return (NULL);
6909 }
6910 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
6911 ret->buffer = buffer;
6912 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00006913 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00006914 return (ret);
6915}
6916
6917/**
Daniel Veillard9d751502003-10-29 13:21:47 +00006918 * xmlSchemaNewDocParserCtxt:
6919 * @doc: a preparsed document tree
6920 *
6921 * Create an XML Schemas parse context for that document.
6922 * NB. The document may be modified during the parsing process.
6923 *
6924 * Returns the parser context or NULL in case of error
6925 */
6926xmlSchemaParserCtxtPtr
6927xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
6928{
6929 xmlSchemaParserCtxtPtr ret;
6930
6931 if (doc == NULL)
6932 return (NULL);
6933
6934 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6935 if (ret == NULL) {
6936 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
6937 NULL);
6938 return (NULL);
6939 }
6940 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
6941 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00006942 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00006943 /* The application has responsibility for the document */
6944 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00006945
6946 return (ret);
6947}
6948
6949/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006950 * xmlSchemaFreeParserCtxt:
6951 * @ctxt: the schema parser context
6952 *
6953 * Free the resources associated to the schema parser context
6954 */
6955void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006956xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
6957{
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006959 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00006960 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006961 xmlFreeDoc(ctxt->doc);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006962 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00006963 xmlFree(ctxt);
6964}
6965
6966/************************************************************************
6967 * *
6968 * Building the content models *
6969 * *
6970 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006971
Daniel Veillard4255d502002-04-16 15:50:10 +00006972/**
6973 * xmlSchemaBuildAContentModel:
6974 * @type: the schema type definition
6975 * @ctxt: the schema parser context
6976 * @name: the element name whose content is being built
6977 *
6978 * Generate the automata sequence needed for that type
6979 */
6980static void
6981xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006982 xmlSchemaParserCtxtPtr ctxt,
6983 const xmlChar * name)
6984{
Daniel Veillard4255d502002-04-16 15:50:10 +00006985 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006986 xmlGenericError(xmlGenericErrorContext,
6987 "Found unexpected type = NULL in %s content model\n",
6988 name);
6989 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990 }
6991 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006992 case XML_SCHEMA_TYPE_ANY: {
6993 xmlAutomataStatePtr start, end;
6994 xmlSchemaWildcardPtr wild;
6995 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00006996
Daniel Veillardc0826a72004-08-10 14:17:33 +00006997 wild = type->attributeWildcard;
6998
6999 if (wild == NULL) {
7000 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
7001 "Internal error: xmlSchemaBuildAContentModel, "
7002 "no wildcard on xsd:any.\n", NULL, NULL);
7003 return;
7004 }
7005
7006 start = ctxt->state;
7007 end = xmlAutomataNewState(ctxt->am);
7008
7009 if (type->maxOccurs == 1) {
7010 if (wild->any == 1) {
7011 /*
7012 * We need to add both transitions:
7013 *
7014 * 1. the {"*", "*"} for elements in a namespace.
7015 */
7016 ctxt->state =
7017 xmlAutomataNewTransition2(ctxt->am,
7018 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7019 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7020 /*
7021 * 2. the {"*"} for elements in no namespace.
7022 */
7023 ctxt->state =
7024 xmlAutomataNewTransition2(ctxt->am,
7025 start, NULL, BAD_CAST "*", NULL, type);
7026 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7027
7028 } else if (wild->nsSet != NULL) {
7029 ns = wild->nsSet;
7030 do {
7031 ctxt->state = start;
7032 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7033 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
7034 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7035 ns = ns->next;
7036 } while (ns != NULL);
7037
7038 } else if (wild->negNsSet != NULL) {
7039 xmlAutomataStatePtr deadEnd;
7040
7041 deadEnd = xmlAutomataNewState(ctxt->am);
7042 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7043 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7044 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7045 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7046 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7047 }
7048 } else {
7049 int counter;
7050 xmlAutomataStatePtr hop;
7051 int maxOccurs =
7052 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
7053 int minOccurs =
7054 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
7055
7056 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
7057 hop = xmlAutomataNewState(ctxt->am);
7058 if (wild->any == 1) {
7059 ctxt->state =
7060 xmlAutomataNewTransition2(ctxt->am,
7061 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7062 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7063 ctxt->state =
7064 xmlAutomataNewTransition2(ctxt->am,
7065 start, NULL, BAD_CAST "*", NULL, type);
7066 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7067 } else if (wild->nsSet != NULL) {
7068 ns = wild->nsSet;
7069 do {
7070 ctxt->state =
7071 xmlAutomataNewTransition2(ctxt->am,
7072 start, NULL, BAD_CAST "*", ns->value, type);
7073 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7074 ns = ns->next;
7075 } while (ns != NULL);
7076
7077 } else if (wild->negNsSet != NULL) {
7078 xmlAutomataStatePtr deadEnd;
7079
7080 deadEnd = xmlAutomataNewState(ctxt->am);
7081 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7082 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
7083 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
7084 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
7085 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7086 }
7087 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
7088 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
7089 }
7090 if (type->minOccurs == 0) {
7091 xmlAutomataNewEpsilon(ctxt->am, start, end);
7092 }
7093 ctxt->state = end;
7094 break;
7095 }
7096 case XML_SCHEMA_TYPE_ELEMENT:{
7097 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) type;
7098
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007099 /* TODO : handle the namespace too */
7100 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007101
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007102 if (elem->maxOccurs >= UNBOUNDED) {
7103 if (elem->minOccurs > 1) {
7104 xmlAutomataStatePtr tmp;
7105 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007106
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007107 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7108 oldstate,
7109 NULL);
7110 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007111
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007112 counter = xmlAutomataNewCounter(ctxt->am,
7113 elem->minOccurs -
7114 1, UNBOUNDED);
Daniel Veillard32370232002-10-16 14:08:14 +00007115
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007116 if (elem->refDecl != NULL) {
7117 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7118 elem->refDecl,
7119 ctxt,
7120 elem->refDecl->
7121 name);
7122 } else {
7123 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007124 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007125 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007126 elem->name,
7127 elem->targetNamespace,
7128 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 }
7130 tmp = ctxt->state;
7131 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7132 counter);
7133 ctxt->state =
7134 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7135 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00007136
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007137 } else {
7138 if (elem->refDecl != NULL) {
7139 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7140 elem->refDecl,
7141 ctxt,
7142 elem->refDecl->
7143 name);
7144 } else {
7145 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +00007146 xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007147 ctxt->state, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007148 elem->name,
7149 elem->targetNamespace,
7150 type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007151 }
7152 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7153 oldstate);
7154 if (elem->minOccurs == 0) {
7155 /* basically an elem* */
7156 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7157 ctxt->state);
7158 }
7159 }
7160 } else if ((elem->maxOccurs > 1) || (elem->minOccurs > 1)) {
7161 xmlAutomataStatePtr tmp;
7162 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00007163
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007164 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7165 oldstate, NULL);
7166 oldstate = ctxt->state;
Daniel Veillard32370232002-10-16 14:08:14 +00007167
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007168 counter = xmlAutomataNewCounter(ctxt->am,
7169 elem->minOccurs - 1,
7170 elem->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007171
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007172 if (elem->refDecl != NULL) {
7173 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7174 elem->refDecl, ctxt,
7175 elem->refDecl->name);
7176 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007177 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007178 ctxt->state,
7179 NULL,
7180 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007181 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007182 type);
7183 }
7184 tmp = ctxt->state;
7185 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7186 counter);
7187 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
7188 NULL,
7189 counter);
7190 if (elem->minOccurs == 0) {
7191 /* basically an elem? */
7192 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7193 ctxt->state);
7194 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00007195
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007196 } else {
7197 if (elem->refDecl != NULL) {
7198 xmlSchemaBuildAContentModel((xmlSchemaTypePtr)
7199 elem->refDecl, ctxt,
7200 elem->refDecl->name);
7201 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007202 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007203 ctxt->state,
7204 NULL,
7205 elem->name,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007206 elem->targetNamespace,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007207 type);
7208 }
7209 if (elem->minOccurs == 0) {
7210 /* basically an elem? */
7211 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7212 ctxt->state);
7213 }
7214 }
7215 break;
7216 }
7217 case XML_SCHEMA_TYPE_SEQUENCE:{
7218 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007219
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007220 /*
7221 * If max and min occurances are default (1) then
7222 * simply iterate over the subtypes
7223 */
7224 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
7225 subtypes = type->subtypes;
7226 while (subtypes != NULL) {
7227 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7228 subtypes = subtypes->next;
7229 }
7230 } else {
7231 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007232
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 if (type->maxOccurs >= UNBOUNDED) {
7234 if (type->minOccurs > 1) {
7235 xmlAutomataStatePtr tmp;
7236 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007237
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007238 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7239 oldstate,
7240 NULL);
7241 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007242
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007243 counter = xmlAutomataNewCounter(ctxt->am,
7244 type->
7245 minOccurs - 1,
7246 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007247
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007248 subtypes = type->subtypes;
7249 while (subtypes != NULL) {
7250 xmlSchemaBuildAContentModel(subtypes, ctxt,
7251 name);
7252 subtypes = subtypes->next;
7253 }
7254 tmp = ctxt->state;
7255 xmlAutomataNewCountedTrans(ctxt->am, tmp,
7256 oldstate, counter);
7257 ctxt->state =
7258 xmlAutomataNewCounterTrans(ctxt->am, tmp,
7259 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00007260
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007261 } else {
7262 subtypes = type->subtypes;
7263 while (subtypes != NULL) {
7264 xmlSchemaBuildAContentModel(subtypes, ctxt,
7265 name);
7266 subtypes = subtypes->next;
7267 }
7268 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
7269 oldstate);
7270 if (type->minOccurs == 0) {
7271 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7272 ctxt->state);
7273 }
7274 }
7275 } else if ((type->maxOccurs > 1)
7276 || (type->minOccurs > 1)) {
7277 xmlAutomataStatePtr tmp;
7278 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00007279
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007280 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
7281 oldstate,
7282 NULL);
7283 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00007284
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007285 counter = xmlAutomataNewCounter(ctxt->am,
7286 type->minOccurs -
7287 1,
7288 type->maxOccurs -
7289 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00007290
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007291 subtypes = type->subtypes;
7292 while (subtypes != NULL) {
7293 xmlSchemaBuildAContentModel(subtypes, ctxt,
7294 name);
7295 subtypes = subtypes->next;
7296 }
7297 tmp = ctxt->state;
7298 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
7299 counter);
7300 ctxt->state =
7301 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
7302 counter);
7303 if (type->minOccurs == 0) {
7304 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7305 ctxt->state);
7306 }
Daniel Veillardb509f152002-04-17 16:28:10 +00007307
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007308 } else {
7309 subtypes = type->subtypes;
7310 while (subtypes != NULL) {
7311 xmlSchemaBuildAContentModel(subtypes, ctxt,
7312 name);
7313 subtypes = subtypes->next;
7314 }
7315 if (type->minOccurs == 0) {
7316 xmlAutomataNewEpsilon(ctxt->am, oldstate,
7317 ctxt->state);
7318 }
7319 }
7320 }
7321 break;
7322 }
7323 case XML_SCHEMA_TYPE_CHOICE:{
7324 xmlSchemaTypePtr subtypes;
7325 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00007326
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007327 start = ctxt->state;
7328 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00007329
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007330 /*
7331 * iterate over the subtypes and remerge the end with an
7332 * epsilon transition
7333 */
7334 if (type->maxOccurs == 1) {
7335 subtypes = type->subtypes;
7336 while (subtypes != NULL) {
7337 ctxt->state = start;
7338 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7339 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
7340 subtypes = subtypes->next;
7341 }
7342 } else {
7343 int counter;
7344 xmlAutomataStatePtr hop;
7345 int maxOccurs = type->maxOccurs == UNBOUNDED ?
7346 UNBOUNDED : type->maxOccurs - 1;
7347 int minOccurs =
7348 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00007349
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007350 /*
7351 * use a counter to keep track of the number of transtions
7352 * which went through the choice.
7353 */
7354 counter =
7355 xmlAutomataNewCounter(ctxt->am, minOccurs,
7356 maxOccurs);
7357 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00007358
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007359 subtypes = type->subtypes;
7360 while (subtypes != NULL) {
7361 ctxt->state = start;
7362 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7363 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
7364 subtypes = subtypes->next;
7365 }
7366 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
7367 counter);
7368 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
7369 counter);
7370 }
7371 if (type->minOccurs == 0) {
7372 xmlAutomataNewEpsilon(ctxt->am, start, end);
7373 }
7374 ctxt->state = end;
7375 break;
7376 }
7377 case XML_SCHEMA_TYPE_ALL:{
7378 xmlAutomataStatePtr start;
7379 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007380
Daniel Veillard3646d642004-06-02 19:19:14 +00007381 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007382 int lax;
7383
7384 subtypes = type->subtypes;
7385 if (subtypes == NULL)
7386 break;
7387 start = ctxt->state;
7388 while (subtypes != NULL) {
7389 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00007390 /*
7391 * the following 'if' was needed to fix bug 139897
7392 * not quite sure why it only needs to be done for
7393 * elements with a 'ref', but it seems to work ok.
7394 */
7395 if (subtypes->ref != NULL)
7396 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00007397 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007398 /* TODO : handle the namespace too */
7399 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
7400 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
7401 ctxt->state, elem->name, 1,
7402 1, subtypes);
7403 } else {
7404 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
7405 ctxt->state, elem->name,
7406 elem->minOccurs,
7407 elem->maxOccurs,
7408 subtypes);
7409 }
7410 subtypes = subtypes->next;
7411 }
7412 lax = type->minOccurs == 0;
7413 ctxt->state =
7414 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
7415 lax);
7416 break;
7417 }
7418 case XML_SCHEMA_TYPE_RESTRICTION:
7419 if (type->subtypes != NULL)
7420 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
7421 break;
7422 case XML_SCHEMA_TYPE_EXTENSION:
7423 if (type->baseType != NULL) {
7424 xmlSchemaTypePtr subtypes;
7425
Daniel Veillardf7627552004-04-22 07:15:40 +00007426 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007427 /* TODO: Change the error code. */
7428 xmlSchemaPCustomErr(ctxt,
7429 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
7430 NULL, type, type->node,
7431 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00007432 return;
7433 }
7434 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007435 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00007436 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007437 subtypes = type->subtypes;
7438 while (subtypes != NULL) {
7439 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
7440 subtypes = subtypes->next;
7441 }
7442 } else if (type->subtypes != NULL)
7443 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
7444 break;
7445 case XML_SCHEMA_TYPE_GROUP:
7446 if (type->subtypes == NULL) {
William M. Brack29aa7722004-05-12 00:27:56 +00007447 xmlSchemaTypePtr rgroup;
7448 if (type->ref != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007449 rgroup = xmlSchemaGetGroup(ctxt->schema, type->ref,
William M. Brack29aa7722004-05-12 00:27:56 +00007450 type->refNs);
7451 if (rgroup == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007452 xmlSchemaPResCompAttrErr(ctxt,
7453 XML_SCHEMAP_SRC_RESOLVE,
7454 NULL, type, NULL,
7455 "ref", type->ref, type->refNs,
7456 XML_SCHEMA_TYPE_GROUP, NULL);
William M. Brack29aa7722004-05-12 00:27:56 +00007457 return;
7458 }
7459 xmlSchemaBuildAContentModel(rgroup, ctxt, name);
7460 break;
7461 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007462 }
7463 case XML_SCHEMA_TYPE_COMPLEX:
7464 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
7465 if (type->subtypes != NULL)
7466 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
7467 break;
7468 default:
7469 xmlGenericError(xmlGenericErrorContext,
7470 "Found unexpected type %d in %s content model\n",
7471 type->type, name);
7472 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007473 }
7474}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007475
Daniel Veillard4255d502002-04-16 15:50:10 +00007476/**
7477 * xmlSchemaBuildContentModel:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007478 * @elem: the element
Daniel Veillard4255d502002-04-16 15:50:10 +00007479 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007480 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00007481 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007482 * Builds the content model of the element.
Daniel Veillard4255d502002-04-16 15:50:10 +00007483 */
7484static void
7485xmlSchemaBuildContentModel(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007486 xmlSchemaParserCtxtPtr ctxt,
7487 const xmlChar * name)
7488{
Daniel Veillard4255d502002-04-16 15:50:10 +00007489 xmlAutomataStatePtr start;
7490
Daniel Veillard4255d502002-04-16 15:50:10 +00007491 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007492 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00007493 if (elem->subtypes == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007494 elem->contentType = XML_SCHEMA_CONTENT_ANY;
7495 return;
Daniel Veillard88c58912002-04-23 07:12:20 +00007496 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007497 if (elem->subtypes->type != XML_SCHEMA_TYPE_COMPLEX)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007498 return;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007499 if ((elem->subtypes->contentType == XML_SCHEMA_CONTENT_BASIC) ||
7500 (elem->subtypes->contentType == XML_SCHEMA_CONTENT_SIMPLE))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007501 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00007502
7503#ifdef DEBUG_CONTENT
7504 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007505 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00007506#endif
7507
Daniel Veillard4255d502002-04-16 15:50:10 +00007508 ctxt->am = xmlNewAutomata();
7509 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007510 xmlGenericError(xmlGenericErrorContext,
7511 "Cannot create automata for elem %s\n", name);
7512 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00007513 }
7514 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
7515 xmlSchemaBuildAContentModel(elem->subtypes, ctxt, name);
7516 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Daniel Veillard4402ab42002-09-12 16:02:56 +00007517 elem->contModel = xmlAutomataCompile(ctxt->am);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007518 if (elem->contModel == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 xmlSchemaPCustomErr(ctxt, XML_SCHEMAS_ERR_INTERNAL,
7520 NULL, (xmlSchemaTypePtr) elem, NULL,
7521 "Failed to compile the content model", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007522 } else if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007523 xmlSchemaPCustomErr(ctxt, XML_SCHEMAS_ERR_NOTDETERMINIST,
7524 NULL, (xmlSchemaTypePtr) elem, NULL,
7525 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00007526 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00007527#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007528 xmlGenericError(xmlGenericErrorContext,
7529 "Content model of %s:\n", name);
7530 xmlRegexpPrint(stderr, elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00007531#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00007532 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00007533 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007534 xmlFreeAutomata(ctxt->am);
7535 ctxt->am = NULL;
7536}
7537
7538/**
7539 * xmlSchemaRefFixupCallback:
7540 * @elem: the schema element context
7541 * @ctxt: the schema parser context
7542 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 * Resolves the references of an element declaration
7544 * or particle, which has an element declaration as it's
7545 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00007546 */
7547static void
7548xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007549 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007551 const xmlChar * context ATTRIBUTE_UNUSED,
7552 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00007553{
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 if ((ctxt == NULL) || (elem == NULL) ||
7555 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007556 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007557 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007559 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00007560
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 /*
7562 * TODO: Evaluate, what errors could occur if the declaration is not
7563 * found. It might be possible that the "typefixup" might crash if
7564 * no ref declaration was found.
7565 */
Daniel Veillardf2a12832003-11-24 13:04:35 +00007566 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007567 if (elemDecl == NULL) {
7568 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007569 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 NULL, (xmlSchemaTypePtr) elem, elem->node,
7571 "ref", elem->ref, elem->refNs,
7572 XML_SCHEMA_TYPE_ELEMENT, NULL);
7573 } else
7574 elem->refDecl = elemDecl;
7575 } else {
7576 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
7577 xmlSchemaTypePtr type;
7578
7579 /* (type definition) ... otherwise the type definition ·resolved·
7580 * to by the ·actual value· of the type [attribute] ...
7581 */
7582 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
7583 elem->namedTypeNs);
7584 if (type == NULL) {
7585 xmlSchemaPResCompAttrErr(ctxt,
7586 XML_SCHEMAP_SRC_RESOLVE,
7587 NULL, (xmlSchemaTypePtr) elem, elem->node,
7588 "type", elem->namedType, elem->namedTypeNs,
7589 XML_SCHEMA_TYPE_BASIC, "type definition");
7590 } else
7591 elem->subtypes = type;
7592 }
7593 if (elem->substGroup != NULL) {
7594 xmlSchemaElementPtr substHead;
7595
7596 /*
7597 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
7598 * substitutionGroup?
7599 */
7600 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
7601 elem->substGroupNs, 0);
7602 if (substHead == NULL) {
7603 xmlSchemaPResCompAttrErr(ctxt,
7604 XML_SCHEMAP_SRC_RESOLVE,
7605 NULL, (xmlSchemaTypePtr) elem, NULL,
7606 "substitutionGroup", elem->substGroup, elem->substGroupNs,
7607 XML_SCHEMA_TYPE_ELEMENT, NULL);
7608 } else {
7609 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
7610 /*
7611 * (type definition)...otherwise the {type definition} of the
7612 * element declaration ·resolved· to by the ·actual value· of
7613 * the substitutionGroup [attribute], if present
7614 */
7615 if (elem->subtypes == NULL)
7616 elem->subtypes = substHead->subtypes;
7617 }
7618 }
7619 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
7620 (elem->substGroup == NULL))
7621 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
7622 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007623}
7624
William M. Bracke7091952004-05-11 15:09:58 +00007625/**
7626 * xmlSchemaParseListRefFixup:
7627 * @type: the schema type definition
7628 * @ctxt: the schema parser context
7629 *
7630 * Fixup of the itemType reference of the list type.
7631 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00007632static void
William M. Bracke7091952004-05-11 15:09:58 +00007633xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007634{
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635
Daniel Veillard01fa6152004-06-29 17:04:39 +00007636 if (((type->base == NULL) &&
7637 (type->subtypes == NULL)) ||
7638 ((type->base != NULL) &&
7639 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007640 /*
7641 * src-list-itemType-or-simpleType
7642 * Either the itemType [attribute] or the <simpleType> [child] of
7643 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007644 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 /*
7646 * TODO: Move this to the parse function.
7647 */
7648 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007649 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007650 NULL, type, type->node,
7651 "The attribute 'itemType' and the <simpleType> child "
7652 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007653 } else if (type->base!= NULL) {
7654 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
7655 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007656 xmlSchemaPResCompAttrErr(ctxt,
7657 XML_SCHEMAP_SRC_RESOLVE,
7658 NULL, type, type->node,
7659 "itemType", type->base, type->baseNs,
7660 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007661 }
7662 }
7663 if ((type->subtypes != NULL) &&
7664 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
7665 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007666}
7667
7668/**
7669 * xmlSchemaParseUnionRefCheck:
7670 * @typeDecl: the schema type definition
7671 * @ctxt: the schema parser context
7672 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00007673 * Checks and builds the memberTypes of the union type.
7674 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00007675 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007676static int
William M. Bracke7091952004-05-11 15:09:58 +00007677xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00007678 xmlSchemaParserCtxtPtr ctxt)
7679{
Daniel Veillardc0826a72004-08-10 14:17:33 +00007680
Daniel Veillard01fa6152004-06-29 17:04:39 +00007681 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
7682 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00007683
Daniel Veillard01fa6152004-06-29 17:04:39 +00007684 /* 1 If the <union> alternative is chosen, then [Definition:]
7685 * define the explicit members as the type definitions ·resolved·
7686 * to by the items in the ·actual value· of the memberTypes [attribute],
7687 * if any, followed by the type definitions corresponding to the
7688 * <simpleType>s among the [children] of <union>, if any.
7689 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00007690
Daniel Veillard01fa6152004-06-29 17:04:39 +00007691 if (type->type != XML_SCHEMA_TYPE_UNION)
7692 return (-1);
7693 if (ctxt->ctxtType == NULL) {
7694 xmlSchemaPErr(ctxt, type->node,
7695 XML_SCHEMAS_ERR_INTERNAL,
7696 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
7697 "available", NULL, NULL);
7698 return (-1);
7699 }
7700 /*
7701 * src-union-memberTypes-or-simpleTypes
7702 * Either the memberTypes [attribute] of the <union> element must
7703 * be non-empty or there must be at least one simpleType [child].
7704 */
7705 if ((type->base == NULL) &&
7706 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00007708 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007709 NULL, NULL, type->node,
7710 "Either the attribute 'memberTypes' must be non-empty "
7711 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007712 }
7713
7714 ctxtType = ctxt->ctxtType;
7715 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007716 xmlAttrPtr attr;
7717 const xmlChar *cur, *end;
7718 xmlChar *tmp;
7719 const xmlChar *localName, *uri;
7720
7721 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00007722 cur = type->base;
7723 do {
7724 while (IS_BLANK_CH(*cur))
7725 cur++;
7726 end = cur;
7727 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7728 end++;
7729 if (end == cur)
7730 break;
7731 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
7733 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
7734 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007735 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 xmlSchemaPResCompAttrErr(ctxt,
7737 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
7738 NULL, NULL, type->node, "memberTypes", localName, uri,
7739 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007740 } else {
7741 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7742 xmlSchemaTypeFixup(memberType, ctxt, NULL);
7743 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
7744 if (link == NULL) {
7745 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
7746 return (-1);
7747 }
7748 link->type = memberType;
7749 link->next = NULL;
7750 if (lastLink == NULL)
7751 ctxtType->memberTypes = link;
7752 else
7753 lastLink->next = link;
7754 lastLink = link;
7755 }
7756 xmlFree(tmp);
7757 cur = end;
7758 } while (*cur != 0);
7759 }
7760 /*
7761 * Add local simple types,
7762 */
7763 memberType = type->subtypes;
7764 while (memberType != NULL) {
7765 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
7766 xmlSchemaTypeFixup(memberType, ctxt, NULL);
7767 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
7768 if (link == NULL) {
7769 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
7770 return (-1);
7771 }
7772 link->type = memberType;
7773 link->next = NULL;
7774 if (lastLink == NULL)
7775 ctxtType->memberTypes = link;
7776 else
7777 lastLink->next = link;
7778 lastLink = link;
7779 memberType = memberType->next;
7780 }
7781 /*
7782 * The actual value is then formed by replacing any union type
7783 * definition in the ·explicit members· with the members of their
7784 * {member type definitions}, in order.
7785 */
7786 link = ctxtType->memberTypes;
7787 while (link != NULL) {
7788 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
7789 subLink = link->type->memberTypes;
7790 if (subLink != NULL) {
7791 link->type = subLink->type;
7792 if (subLink->next != NULL) {
7793 lastLink = link->next;
7794 subLink = subLink->next;
7795 prevLink = link;
7796 while (subLink != NULL) {
7797 newLink = (xmlSchemaTypeLinkPtr)
7798 xmlMalloc(sizeof(xmlSchemaTypeLink));
7799 if (newLink == NULL) {
7800 xmlSchemaPErrMemory(ctxt, "allocating a type link",
7801 NULL);
7802 return (-1);
7803 }
7804 newLink->type = memberType;
7805 prevLink->next = newLink;
7806 prevLink = newLink;
7807 newLink->next = lastLink;
7808
7809 subLink = subLink->next;
7810 }
7811 }
7812 }
7813 }
7814 link = link->next;
7815 }
7816
7817 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00007818}
7819
Daniel Veillard4255d502002-04-16 15:50:10 +00007820/**
Daniel Veillard3646d642004-06-02 19:19:14 +00007821 * xmlSchemaIsDerivedFromBuiltInType:
7822 * @ctxt: the schema parser context
7823 * @type: the type definition
7824 * @valType: the value type
7825 *
7826 *
7827 * Returns 1 if the type has the given value type, or
7828 * is derived from such a type.
7829 */
William M. Brack803812b2004-06-03 02:11:24 +00007830static int
Daniel Veillard3646d642004-06-02 19:19:14 +00007831xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
7832 xmlSchemaTypePtr type, int valType)
7833{
7834 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007835 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00007836 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007837 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00007838 return(1);
7839 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
7840 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
7841 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
7842 ((xmlSchemaAttributePtr) type)->subtypes, valType));
7843 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
7844 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
7845 if (type->baseType != NULL)
7846 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
7847 valType));
7848 } else if ((type->subtypes != NULL) &&
7849 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
7850 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
7851 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
7852 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
7853 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
7854 valType));
7855 }
7856
7857 return (0);
7858}
7859
7860/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00007861 * xmlSchemaIsDerivedFromBuiltInType:
7862 * @type: the simpleType definition
7863 *
7864 * Returns the primitive type of the given type or
7865 * NULL in case of error.
7866 */
7867static xmlSchemaTypePtr
7868xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
7869{
7870 while (type != NULL) {
7871 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
7872 return (type);
7873 type = type->baseType;
7874 }
7875
7876 return (NULL);
7877}
7878
7879
7880/**
Daniel Veillard3646d642004-06-02 19:19:14 +00007881 * xmlSchemaBuildAttributeUsesOwned:
7882 * @ctxt: the schema parser context
7883 * @type: the complex type definition
7884 * @cur: the attribute declaration list
7885 * @lastUse: the top of the attribute use list
7886 *
7887 * Builds the attribute uses list on the given complex type.
7888 * This one is supposed to be called by
7889 * xmlSchemaBuildAttributeValidation only.
7890 */
7891static int
7892xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
7893 xmlSchemaAttributePtr cur,
7894 xmlSchemaAttributeLinkPtr *uses,
7895 xmlSchemaAttributeLinkPtr *lastUse)
7896{
7897 xmlSchemaAttributeLinkPtr tmp;
7898 while (cur != NULL) {
7899 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7900 /*
7901 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
7902 * to by the ·actual value·s of the ref [attribute] of the
7903 * <attributeGroup> [children], if any."
7904 */
7905 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
7906 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
7907 lastUse) == -1) {
7908 return (-1);
7909 }
7910 } else {
7911 /* W3C: "1 The set of attribute uses corresponding to the
7912 * <attribute> [children], if any."
7913 */
7914 tmp = (xmlSchemaAttributeLinkPtr)
7915 xmlMalloc(sizeof(xmlSchemaAttributeLink));
7916 if (tmp == NULL) {
7917 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
7918 return (-1);
7919 }
7920 tmp->attr = cur;
7921 tmp->next = NULL;
7922 if (*uses == NULL)
7923 *uses = tmp;
7924 else
7925 (*lastUse)->next = tmp;
7926 *lastUse = tmp;
7927 }
7928 cur = cur->next;
7929 }
7930 return (0);
7931}
7932
Daniel Veillard50355f02004-06-08 17:52:16 +00007933/**
7934 * xmlSchemaCloneWildcardNsConstraints:
7935 * @ctxt: the schema parser context
7936 * @dest: the destination wildcard
7937 * @source: the source wildcard
7938 *
7939 * Clones the namespace constraints of source
7940 * and assignes them to dest.
7941 * Returns -1 on internal error, 0 otherwise.
7942 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007943static int
7944xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
7945 xmlSchemaWildcardPtr *dest,
7946 xmlSchemaWildcardPtr source)
7947{
7948 xmlSchemaWildcardNsPtr cur, tmp, last;
7949
7950 if ((source == NULL) || (*dest == NULL))
7951 return(-1);
7952 (*dest)->any = source->any;
7953 cur = source->nsSet;
7954 last = NULL;
7955 while (cur != NULL) {
7956 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
7957 if (tmp == NULL)
7958 return(-1);
7959 tmp->value = cur->value;
7960 if (last == NULL)
7961 (*dest)->nsSet = tmp;
7962 else
7963 last->next = tmp;
7964 last = tmp;
7965 cur = cur->next;
7966 }
7967 if ((*dest)->negNsSet != NULL)
7968 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
7969 if (source->negNsSet != NULL) {
7970 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
7971 if ((*dest)->negNsSet == NULL)
7972 return(-1);
7973 (*dest)->negNsSet->value = source->negNsSet->value;
7974 } else
7975 (*dest)->negNsSet = NULL;
7976 return(0);
7977}
7978
Daniel Veillard50355f02004-06-08 17:52:16 +00007979/**
7980 * xmlSchemaUnionWildcards:
7981 * @ctxt: the schema parser context
7982 * @completeWild: the first wildcard
7983 * @curWild: the second wildcard
7984 *
7985 * Unions the namespace constraints of the given wildcards.
7986 * @completeWild will hold the resulting union.
7987 * Returns a positive error code on failure, -1 in case of an
7988 * internal error, 0 otherwise.
7989 */
Daniel Veillard3646d642004-06-02 19:19:14 +00007990static int
7991xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
7992 xmlSchemaWildcardPtr completeWild,
7993 xmlSchemaWildcardPtr curWild)
7994{
7995 xmlSchemaWildcardNsPtr cur, curB, tmp;
7996
7997 /*
7998 * 1 If O1 and O2 are the same value, then that value must be the
7999 * value.
8000 */
8001 if ((completeWild->any == curWild->any) &&
8002 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8003 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8004
8005 if ((completeWild->negNsSet == NULL) ||
8006 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8007
8008 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008009 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008010
8011 /*
8012 * Check equality of sets.
8013 */
8014 cur = completeWild->nsSet;
8015 while (cur != NULL) {
8016 found = 0;
8017 curB = curWild->nsSet;
8018 while (curB != NULL) {
8019 if (cur->value == curB->value) {
8020 found = 1;
8021 break;
8022 }
8023 curB = curB->next;
8024 }
8025 if (!found)
8026 break;
8027 cur = cur->next;
8028 }
8029 if (found)
8030 return(0);
8031 } else
8032 return(0);
8033 }
8034 }
8035 /*
8036 * 2 If either O1 or O2 is any, then any must be the value
8037 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008038 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008039 if (completeWild->any == 0) {
8040 completeWild->any = 1;
8041 if (completeWild->nsSet != NULL) {
8042 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8043 completeWild->nsSet = NULL;
8044 }
8045 if (completeWild->negNsSet != NULL) {
8046 xmlFree(completeWild->negNsSet);
8047 completeWild->negNsSet = NULL;
8048 }
8049 }
Daniel Veillard50355f02004-06-08 17:52:16 +00008050 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008051 }
8052 /*
8053 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
8054 * then the union of those sets must be the value.
8055 */
8056 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8057 int found;
8058 xmlSchemaWildcardNsPtr start;
8059
8060 cur = curWild->nsSet;
8061 start = completeWild->nsSet;
8062 while (cur != NULL) {
8063 found = 0;
8064 curB = start;
8065 while (curB != NULL) {
8066 if (cur->value == curB->value) {
8067 found = 1;
8068 break;
8069 }
8070 curB = curB->next;
8071 }
8072 if (!found) {
8073 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
8074 if (tmp == NULL)
8075 return (-1);
8076 tmp->value = cur->value;
8077 tmp->next = completeWild->nsSet;
8078 completeWild->nsSet = tmp;
8079 }
8080 cur = cur->next;
8081 }
8082
8083 return(0);
8084 }
8085 /*
8086 * 4 If the two are negations of different values (namespace names
8087 * or ·absent·), then a pair of not and ·absent· must be the value.
8088 */
8089 if ((completeWild->negNsSet != NULL) &&
8090 (curWild->negNsSet != NULL) &&
8091 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
8092 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00008093
8094 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008095 }
8096 /*
8097 * 5.
8098 */
8099 if (((completeWild->negNsSet != NULL) &&
8100 (completeWild->negNsSet->value != NULL) &&
8101 (curWild->nsSet != NULL)) ||
8102 ((curWild->negNsSet != NULL) &&
8103 (curWild->negNsSet->value != NULL) &&
8104 (completeWild->nsSet != NULL))) {
8105
8106 int nsFound, absentFound = 0;
8107
8108 if (completeWild->nsSet != NULL) {
8109 cur = completeWild->nsSet;
8110 curB = curWild->negNsSet;
8111 } else {
8112 cur = curWild->nsSet;
8113 curB = completeWild->negNsSet;
8114 }
8115 nsFound = 0;
8116 while (cur != NULL) {
8117 if (cur->value == NULL)
8118 absentFound = 1;
8119 else if (cur->value == curB->value)
8120 nsFound = 1;
8121 if (nsFound && absentFound)
8122 break;
8123 cur = cur->next;
8124 }
8125
8126 if (nsFound && absentFound) {
8127 /*
8128 * 5.1 If the set S includes both the negated namespace
8129 * name and ·absent·, then any must be the value.
8130 */
8131 completeWild->any = 1;
8132 if (completeWild->nsSet != NULL) {
8133 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8134 completeWild->nsSet = NULL;
8135 }
8136 if (completeWild->negNsSet != NULL) {
8137 xmlFree(completeWild->negNsSet);
8138 completeWild->negNsSet = NULL;
8139 }
8140 } else if (nsFound && (!absentFound)) {
8141 /*
8142 * 5.2 If the set S includes the negated namespace name
8143 * but not ·absent·, then a pair of not and ·absent· must
8144 * be the value.
8145 */
8146 if (completeWild->nsSet != NULL) {
8147 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8148 completeWild->nsSet = NULL;
8149 }
8150 if (completeWild->negNsSet == NULL) {
8151 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8152 if (completeWild->negNsSet == NULL)
8153 return (-1);
8154 }
8155 completeWild->negNsSet->value = NULL;
8156 } else if ((!nsFound) && absentFound) {
8157 /*
8158 * 5.3 If the set S includes ·absent· but not the negated
8159 * namespace name, then the union is not expressible.
8160 */
8161 xmlSchemaPErr(ctxt, completeWild->node,
8162 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008163 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008164 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008165 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008166 } else if ((!nsFound) && (!absentFound)) {
8167 /*
8168 * 5.4 If the set S does not include either the negated namespace
8169 * name or ·absent·, then whichever of O1 or O2 is a pair of not
8170 * and a namespace name must be the value.
8171 */
8172 if (completeWild->negNsSet == NULL) {
8173 if (completeWild->nsSet != NULL) {
8174 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8175 completeWild->nsSet = NULL;
8176 }
8177 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8178 if (completeWild->negNsSet == NULL)
8179 return (-1);
8180 completeWild->negNsSet->value = curWild->negNsSet->value;
8181 }
8182 }
8183 return (0);
8184 }
8185 /*
8186 * 6.
8187 */
8188 if (((completeWild->negNsSet != NULL) &&
8189 (completeWild->negNsSet->value == NULL) &&
8190 (curWild->nsSet != NULL)) ||
8191 ((curWild->negNsSet != NULL) &&
8192 (curWild->negNsSet->value == NULL) &&
8193 (completeWild->nsSet != NULL))) {
8194
8195 if (completeWild->nsSet != NULL) {
8196 cur = completeWild->nsSet;
8197 } else {
8198 cur = curWild->nsSet;
8199 }
8200 while (cur != NULL) {
8201 if (cur->value == NULL) {
8202 /*
8203 * 6.1 If the set S includes ·absent·, then any must be the
8204 * value.
8205 */
8206 completeWild->any = 1;
8207 if (completeWild->nsSet != NULL) {
8208 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8209 completeWild->nsSet = NULL;
8210 }
8211 if (completeWild->negNsSet != NULL) {
8212 xmlFree(completeWild->negNsSet);
8213 completeWild->negNsSet = NULL;
8214 }
8215 return (0);
8216 }
8217 cur = cur->next;
8218 }
8219 if (completeWild->negNsSet == NULL) {
8220 /*
8221 * 6.2 If the set S does not include ·absent·, then a pair of not
8222 * and ·absent· must be the value.
8223 */
8224 if (completeWild->nsSet != NULL) {
8225 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
8226 completeWild->nsSet = NULL;
8227 }
8228 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
8229 if (completeWild->negNsSet == NULL)
8230 return (-1);
8231 completeWild->negNsSet->value = NULL;
8232 }
8233 return (0);
8234 }
8235 return (0);
8236
8237}
8238
Daniel Veillard50355f02004-06-08 17:52:16 +00008239/**
8240 * xmlSchemaIntersectWildcards:
8241 * @ctxt: the schema parser context
8242 * @completeWild: the first wildcard
8243 * @curWild: the second wildcard
8244 *
8245 * Intersects the namespace constraints of the given wildcards.
8246 * @completeWild will hold the resulting intersection.
8247 * Returns a positive error code on failure, -1 in case of an
8248 * internal error, 0 otherwise.
8249 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008250static int
8251xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
8252 xmlSchemaWildcardPtr completeWild,
8253 xmlSchemaWildcardPtr curWild)
8254{
William M. Brack803812b2004-06-03 02:11:24 +00008255 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008256
8257 /*
8258 * 1 If O1 and O2 are the same value, then that value must be the
8259 * value.
8260 */
8261 if ((completeWild->any == curWild->any) &&
8262 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
8263 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
8264
8265 if ((completeWild->negNsSet == NULL) ||
8266 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
8267
8268 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00008269 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00008270
8271 /*
8272 * Check equality of sets.
8273 */
8274 cur = completeWild->nsSet;
8275 while (cur != NULL) {
8276 found = 0;
8277 curB = curWild->nsSet;
8278 while (curB != NULL) {
8279 if (cur->value == curB->value) {
8280 found = 1;
8281 break;
8282 }
8283 curB = curB->next;
8284 }
8285 if (!found)
8286 break;
8287 cur = cur->next;
8288 }
8289 if (found)
8290 return(0);
8291 } else
8292 return(0);
8293 }
8294 }
8295 /*
8296 * 2 If either O1 or O2 is any, then the other must be the value.
8297 */
8298 if ((completeWild->any != curWild->any) && (completeWild->any)) {
8299 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8300 return(-1);
8301 return(0);
8302 }
8303 /*
8304 * 3 If either O1 or O2 is a pair of not and a value (a namespace
8305 * name or ·absent·) and the other is a set of (namespace names or
8306 * ·absent·), then that set, minus the negated value if it was in
8307 * the set, minus ·absent· if it was in the set, must be the value.
8308 */
8309 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
8310 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
8311 const xmlChar *neg;
8312
8313 if (completeWild->nsSet == NULL) {
8314 neg = completeWild->negNsSet->value;
8315 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
8316 return(-1);
8317 } else
8318 neg = curWild->negNsSet->value;
8319 /*
8320 * Remove absent and negated.
8321 */
8322 prev = NULL;
8323 cur = completeWild->nsSet;
8324 while (cur != NULL) {
8325 if (cur->value == NULL) {
8326 if (prev == NULL)
8327 completeWild->nsSet = cur->next;
8328 else
8329 prev->next = cur->next;
8330 xmlFree(cur);
8331 break;
8332 }
8333 prev = cur;
8334 cur = cur->next;
8335 }
8336 if (neg != NULL) {
8337 prev = NULL;
8338 cur = completeWild->nsSet;
8339 while (cur != NULL) {
8340 if (cur->value == neg) {
8341 if (prev == NULL)
8342 completeWild->nsSet = cur->next;
8343 else
8344 prev->next = cur->next;
8345 xmlFree(cur);
8346 break;
8347 }
8348 prev = cur;
8349 cur = cur->next;
8350 }
8351 }
8352
8353 return(0);
8354 }
8355 /*
8356 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
8357 * then the intersection of those sets must be the value.
8358 */
8359 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
8360 int found;
8361
8362 cur = completeWild->nsSet;
8363 prev = NULL;
8364 while (cur != NULL) {
8365 found = 0;
8366 curB = curWild->nsSet;
8367 while (curB != NULL) {
8368 if (cur->value == curB->value) {
8369 found = 1;
8370 break;
8371 }
8372 curB = curB->next;
8373 }
8374 if (!found) {
8375 if (prev == NULL)
8376 completeWild->nsSet = cur->next;
8377 else
8378 prev->next = cur->next;
8379 tmp = cur->next;
8380 xmlFree(cur);
8381 cur = tmp;
8382 continue;
8383 }
8384 prev = cur;
8385 cur = cur->next;
8386 }
8387
8388 return(0);
8389 }
8390 /* 5 If the two are negations of different namespace names,
8391 * then the intersection is not expressible
8392 */
8393 if ((completeWild->negNsSet != NULL) &&
8394 (curWild->negNsSet != NULL) &&
8395 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
8396 (completeWild->negNsSet->value != NULL) &&
8397 (curWild->negNsSet->value != NULL)) {
8398
8399 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008400 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00008401 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008402 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008403 }
8404 /*
8405 * 6 If the one is a negation of a namespace name and the other
8406 * is a negation of ·absent·, then the one which is the negation
8407 * of a namespace name must be the value.
8408 */
8409 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
8410 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
8411 (completeWild->negNsSet->value == NULL)) {
8412 completeWild->negNsSet->value = curWild->negNsSet->value;
8413 }
8414 return(0);
8415}
8416
Daniel Veillard50355f02004-06-08 17:52:16 +00008417/**
8418 * xmlSchemaIsWildcardNsConstraintSubset:
8419 * @ctxt: the schema parser context
8420 * @wildA: the first wildcard
8421 * @wildB: the second wildcard
8422 *
8423 * Returns 1 if the namespace constraint of @wildA is an intensional
8424 * subset of @wildB, 0 otherwise.
8425 */
8426static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00008427xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
8428 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00008429{
Daniel Veillard3646d642004-06-02 19:19:14 +00008430
Daniel Veillard50355f02004-06-08 17:52:16 +00008431 /*
8432 * Schema Component Constraint: Wildcard Subset
8433 */
8434 /*
8435 * 1 super must be any.
8436 */
8437 if (wildB->any)
8438 return (1);
8439 /*
8440 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
8441 * 2.2 super must be a pair of not and the same value.
8442 */
8443 if ((wildA->negNsSet != NULL) &&
8444 (wildB->negNsSet != NULL) &&
8445 (wildA->negNsSet->value == wildA->negNsSet->value))
8446 return (1);
8447 /*
8448 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
8449 */
8450 if (wildA->nsSet != NULL) {
8451 /*
8452 * 3.2.1 super must be the same set or a superset thereof.
8453 */
8454 if (wildB->nsSet != NULL) {
8455 xmlSchemaWildcardNsPtr cur, curB;
8456 int found = 0;
8457
8458 cur = wildA->nsSet;
8459 while (cur != NULL) {
8460 found = 0;
8461 curB = wildB->nsSet;
8462 while (curB != NULL) {
8463 if (cur->value == curB->value) {
8464 found = 1;
8465 break;
8466 }
8467 curB = curB->next;
8468 }
8469 if (!found)
8470 return (0);
8471 cur = cur->next;
8472 }
8473 if (found)
8474 return (1);
8475 } else if (wildB->negNsSet != NULL) {
8476 xmlSchemaWildcardNsPtr cur;
8477 /*
8478 * 3.2.2 super must be a pair of not and a namespace name or
8479 * ·absent· and that value must not be in sub's set.
8480 */
8481 cur = wildA->nsSet;
8482 while (cur != NULL) {
8483 if (cur->value == wildB->negNsSet->value)
8484 return (0);
8485 cur = cur->next;
8486 }
8487 return (1);
8488 }
8489 }
8490 return (0);
8491}
8492
8493/**
8494 * xmlSchemaBuildCompleteAttributeWildcard:
8495 * @ctxt: the schema parser context
8496 * @attrs: the attribute list
8497 * @completeWild: the resulting complete wildcard
8498 *
8499 * Returns -1 in case of an internal error, 0 otherwise.
8500 */
8501static int
8502xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
8503 xmlSchemaAttributePtr attrs,
8504 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00008505{
8506 while (attrs != NULL) {
8507 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
8508 xmlSchemaAttributeGroupPtr group;
8509
8510 group = (xmlSchemaAttributeGroupPtr) attrs;
8511 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
8512 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00008513 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
8514 group->attributes, &group->attributeWildcard) == -1)
8515 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008516 }
8517 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
8518 }
8519 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00008520 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008521 /*
8522 * Copy the first encountered wildcard as context, except for the annotation.
8523 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008524 *completeWild = xmlSchemaAddWildcard(ctxt);
8525 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
8526 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
8527 completeWild, group->attributeWildcard) == -1)
8528 return (-1);
8529 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00008530 /*
8531 * Although the complete wildcard might not correspond to any
8532 * node in the schema, we will save this context node.
8533 */
Daniel Veillard50355f02004-06-08 17:52:16 +00008534 (*completeWild)->node = group->attributeWildcard->node;
8535
8536 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
8537 xmlSchemaFreeWildcard(*completeWild);
8538 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008539 }
8540 }
8541 }
8542 attrs = attrs->next;
8543 }
8544
Daniel Veillard50355f02004-06-08 17:52:16 +00008545 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00008546}
8547
8548/**
8549 * xmlSchemaMatchesWildcardNs:
8550 * @wild: the wildcard
8551 * @ns: the namespace
8552 *
8553 *
8554 * Returns 1 if the given namespace matches the wildcard,
8555 * 0 otherwise.
8556 */
8557static int
8558xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
8559{
8560 if (wild == NULL)
8561 return(0);
8562
8563 if (wild->any)
8564 return(1);
8565 else if (wild->nsSet != NULL) {
8566 xmlSchemaWildcardNsPtr cur;
8567
8568 cur = wild->nsSet;
8569 while (cur != NULL) {
8570 if (xmlStrEqual(cur->value, ns))
8571 return(1);
8572 cur = cur->next;
8573 }
8574 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
8575 (!xmlStrEqual(wild->negNsSet->value, ns)))
8576 return(1);
8577
8578 return(0);
8579}
8580
8581/**
8582 * xmlSchemaBuildAttributeValidation:
8583 * @ctxt: the schema parser context
8584 * @type: the complex type definition
8585 *
8586 *
8587 * Builds the wildcard and the attribute uses on the given complex type.
8588 * Returns -1 if an internal error occurs, 0 otherwise.
8589 */
8590static int
8591xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
8592{
8593 xmlSchemaTypePtr baseType = NULL;
8594 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00008595 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00008596 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008597 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00008598 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008599 xmlChar *str = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00008600
Daniel Veillard01fa6152004-06-29 17:04:39 +00008601 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00008602 /*
8603 * Complex Type Definition with complex content Schema Component.
8604 *
8605 * Attribute uses.
8606 */
8607 if (type->attributeUses != NULL) {
8608 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008609 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00008610 "attribute uses already builded.\n",
8611 NULL, NULL);
8612 return (-1);
8613 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008614 if (type->baseType == NULL) {
8615 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAS_ERR_INTERNAL,
8616 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00008617 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00008618 type->name, NULL);
8619 return (-1);
8620 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008621 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008622 if (baseType == anyType)
8623 baseIsAnyType = 1;
8624 /*
8625 * Inherit the attribute uses of the base type.
8626 */
8627 /*
8628 * NOTE: It is allowed to "extend" the anyType complex type.
8629 */
8630 if (!baseIsAnyType) {
8631 if (baseType != NULL) {
8632 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
8633 tmp = (xmlSchemaAttributeLinkPtr)
8634 xmlMalloc(sizeof(xmlSchemaAttributeLink));
8635 if (tmp == NULL) {
8636 xmlSchemaPErrMemory(ctxt,
8637 "building attribute uses of complexType", NULL);
8638 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00008639 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008640 tmp->attr = cur->attr;
8641 tmp->next = NULL;
8642 if (type->attributeUses == NULL) {
8643 type->attributeUses = tmp;
8644 } else
8645 lastBaseUse->next = tmp;
8646 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00008647 }
8648 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008649 }
8650 if ((type->subtypes != NULL) &&
8651 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
8652 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
8653 attrs = type->subtypes->subtypes->attributes;
8654 type->attributeWildcard = type->subtypes->subtypes->attributeWildcard;
8655 } else {
8656 /* Short hand form of the complexType. */
8657 attrs = type->attributes;
8658 }
8659 /*
8660 * Handle attribute wildcards.
8661 */
8662 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
8663 attrs, &type->attributeWildcard) == -1) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008664 if ((type->attributeWildcard != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00008665 /* Either we used the short hand form... */
8666 ((type->subtypes == NULL) ||
8667 /* Or complexType -> restriction/extension */
8668 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
Daniel Veillard3646d642004-06-02 19:19:14 +00008669 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008670 return (-1);
8671 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008672 /*
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008673 * TODO: This "onwed_attr_wildcard" is quite sensless: we should
8674 * create the wildcard right from the start on the complexType,
8675 * rather than on the <restriction>/<extension>.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008676 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008677 if ((type->attributeWildcard != NULL) &&
8678 /* Either we used the short hand form... */
8679 ((type->subtypes == NULL) ||
8680 /* Or complexType -> restriction/extension */
8681 (type->attributeWildcard != type->subtypes->subtypes->attributeWildcard)))
8682 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
8683
8684 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
8685 ((baseIsAnyType) ||
8686 ((baseType != NULL) &&
8687 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
8688 (baseType->attributeWildcard != NULL)))) {
8689 if (type->attributeWildcard != NULL) {
8690 /*
8691 * Union the complete wildcard with the base wildcard.
8692 */
8693 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
8694 baseType->attributeWildcard) == -1)
8695 return (-1);
8696 } else {
8697 /*
8698 * Just inherit the wildcard.
8699 */
8700 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00008701 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008702 }
8703
8704 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
8705 if (type->attributeWildcard != NULL) {
8706 /*
8707 * Derivation Valid (Restriction, Complex)
8708 * 4.1 The {base type definition} must also have one.
8709 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008710 if (baseType->attributeWildcard == NULL) {
8711 xmlSchemaPCustomErr(ctxt,
8712 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
8713 NULL, type, NULL,
8714 "The type has an attribute wildcard, "
8715 "but the base type %s does not have one",
8716 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
8717 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008718 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008719 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008720 type->attributeWildcard, baseType->attributeWildcard) == 0) {
8721 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008722 xmlSchemaPCustomErr(ctxt,
8723 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
8724 NULL, type, NULL,
8725 "The attribute wildcard is not a valid "
8726 "subset of the wildcard in the base type %s",
8727 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
8728 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008729 return (1);
8730 }
8731 /* 4.3 Unless the {base type definition} is the ·ur-type
8732 * definition·, the complex type definition's {attribute
8733 * wildcard}'s {process contents} must be identical to or
8734 * stronger than the {base type definition}'s {attribute
8735 * wildcard}'s {process contents}, where strict is stronger
8736 * than lax is stronger than skip.
8737 */
8738 if ((type->baseType != anyType) &&
8739 (type->attributeWildcard->processContents <
8740 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008741 xmlSchemaPCustomErr(ctxt,
8742 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
8743 NULL, type, NULL,
8744 "The 'process contents' of the attribute wildcard is weaker than "
8745 "the one in the base type %s",
8746 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
8747 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008748 return (1);
8749 }
8750 }
8751 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
8752 /*
8753 * Derivation Valid (Extension)
8754 * At this point the type and the base have both, either
8755 * no wildcard or a wildcard.
8756 */
8757 if ((baseType->attributeWildcard != NULL) &&
8758 (baseType->attributeWildcard != type->attributeWildcard)) {
8759 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008760 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008761 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008762 xmlSchemaPCustomErr(ctxt,
8763 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
8764 NULL, type, NULL,
8765 "The attribute wildcard is not a valid "
8766 "superset of the one in the base type %s",
8767 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
8768 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008769 return (1);
8770 }
8771 }
8772 }
8773
Daniel Veillard3646d642004-06-02 19:19:14 +00008774 /*
8775 * Gather attribute uses defined by this type.
8776 */
8777 if (attrs != NULL) {
8778 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
8779 &uses, &lastUse) == -1) {
8780 return (-1);
8781 }
8782 }
8783 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
8784 * "Two distinct attribute declarations in the {attribute uses} must
8785 * not have identical {name}s and {target namespace}s."
8786 *
8787 * For "extension" this is done further down.
8788 */
8789 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
8790 cur = uses;
8791 while (cur != NULL) {
8792 tmp = cur->next;
8793 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008794 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
8795 xmlSchemaGetAttrName(tmp->attr))) &&
8796 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
8797 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
8798
8799 xmlSchemaPAttrUseErr(ctxt,
8800 XML_SCHEMAP_CT_PROPS_CORRECT_4,
8801 NULL, type, NULL, cur->attr,
8802 "Duplicate attribute use %s specified",
8803 xmlSchemaFormatNsUriLocal(&str,
8804 xmlSchemaGetAttrTargetNsURI(tmp->attr),
8805 xmlSchemaGetAttrName(tmp->attr))
8806 );
8807 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00008808 break;
8809 }
8810 tmp = tmp->next;
8811 }
8812 cur = cur->next;
8813 }
8814 }
8815 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
8816 /*
8817 * Derive by restriction.
8818 */
8819 if (baseIsAnyType) {
8820 type->attributeUses = uses;
8821 } else {
8822 int found;
8823
8824 cur = uses;
8825 while (cur != NULL) {
8826 found = 0;
8827 base = type->attributeUses;
8828 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008829 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
8830 xmlSchemaGetAttrName(base->attr)) &&
8831 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
8832 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008833
Daniel Veillardc0826a72004-08-10 14:17:33 +00008834 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00008835 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
8836 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
8837 /*
8838 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +00008839 */
8840 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00008841 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008842 NULL, type, NULL, cur->attr,
8843 "The 'optional' use is inconsistent with a matching "
8844 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008845 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
8846 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
8847 /*
8848 * derivation-ok-restriction 3
8849 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008850 xmlSchemaPCustomErr(ctxt,
8851 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
8852 NULL, type, NULL,
8853 "A matching attribute use for the 'required' "
8854 "attribute use %s of the base type is missing",
8855 xmlSchemaFormatNsUriLocal(&str,
8856 xmlSchemaGetAttrTargetNsURI(base->attr),
8857 xmlSchemaGetAttrName(base->attr)));
8858 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +00008859 } else {
8860 /*
8861 * Override the attribute use.
8862 */
8863 base->attr = cur->attr;
8864 }
8865 /*
8866 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +00008867 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +00008868 */
8869 break;
8870 }
8871 base = base->next;
8872 }
8873
8874 if (!found) {
8875 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
8876 /*
8877 * derivation-ok-restriction 2.2
8878 */
8879 if ((type->attributeWildcard != NULL) &&
8880 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
8881 cur->attr->targetNamespace))
8882 found = 1;
8883
8884 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008885 xmlSchemaPAttrUseErr(ctxt,
8886 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
8887 NULL, type, NULL, cur->attr,
8888 "Neither a matching attribute use, "
8889 "nor a matching wildcard in the base type does exist",
8890 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00008891 } else {
8892 /*
8893 * Add the attribute use.
8894 *
8895 * Note that this may lead to funny derivation error reports, if
8896 * multiple equal attribute uses exist; but this is not
8897 * allowed anyway, and it will be reported beforehand.
8898 */
8899 tmp = cur;
8900 if (prev != NULL)
8901 prev->next = cur->next;
8902 else
8903 uses = cur->next;
8904 cur = cur->next;
8905 if (type->attributeUses == NULL) {
8906 type->attributeUses = tmp;
8907 } else
8908 lastBaseUse->next = tmp;
8909 lastBaseUse = tmp;
8910
8911 continue;
8912 }
8913 }
8914 }
8915 prev = cur;
8916 cur = cur->next;
8917 }
8918 if (uses != NULL)
8919 xmlSchemaFreeAttributeUseList(uses);
8920 }
8921 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
8922 /*
8923 * The spec allows only appending, and not other kinds of extensions.
8924 *
8925 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
8926 */
8927 if (uses != NULL) {
8928 if (type->attributeUses == NULL) {
8929 type->attributeUses = uses;
8930 } else
8931 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00008932 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008933 } else {
8934 /*
Daniel Veillard50355f02004-06-08 17:52:16 +00008935 * Derive implicitely from the ur-type.
8936 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008937 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +00008938 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008939 /*
8940 * 3.4.6 -> Complex Type Definition Properties Correct
8941 */
8942 if (type->attributeUses != NULL) {
8943 cur = type->attributeUses;
8944 prev = NULL;
8945 while (cur != NULL) {
8946 /*
8947 * 4. Two distinct attribute declarations in the {attribute uses} must
8948 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +00008949 *
Daniel Veillard3646d642004-06-02 19:19:14 +00008950 * Note that this was already done for "restriction" and types derived from
8951 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +00008952 */
Daniel Veillard3646d642004-06-02 19:19:14 +00008953 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
8954 tmp = cur->next;
8955 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008956 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
8957 xmlSchemaGetAttrName(tmp->attr))) &&
8958 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
8959 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008960
Daniel Veillardc0826a72004-08-10 14:17:33 +00008961 xmlSchemaPAttrUseErr(ctxt,
8962 XML_SCHEMAP_CT_PROPS_CORRECT_4,
8963 NULL, type, NULL, tmp->attr,
8964 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00008965 break;
8966 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008967 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00008968 }
8969 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008970 /*
8971 * 5. Two distinct attribute declarations in the {attribute uses} must
8972 * not have {type definition}s which are or are derived from ID.
8973 */
8974 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +00008975 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008976 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008977 xmlSchemaPAttrUseErr(ctxt,
8978 XML_SCHEMAP_CT_PROPS_CORRECT_5,
8979 NULL, type, NULL, cur->attr,
8980 "There must not exist more than one attribute use, "
8981 "declared of type 'ID' or derived from it",
8982 NULL);
8983 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +00008984 }
Daniel Veillard3646d642004-06-02 19:19:14 +00008985 id = cur;
8986 }
8987 /*
8988 * Remove "prohibited" attribute uses. The reason this is done at this late
8989 * stage is to be able to catch dublicate attribute uses. So we had to keep
8990 * prohibited uses in the list as well.
8991 */
8992 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
8993 tmp = cur;
8994 if (prev == NULL)
8995 type->attributeUses = cur->next;
8996 else
8997 prev->next = cur->next;
8998 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +00008999 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +00009000 } else {
9001 prev = cur;
9002 cur = cur->next;
9003 }
9004 }
9005 }
9006 /*
9007 * TODO: This check should be removed if we are 100% sure of
9008 * the base type attribute uses already being built.
9009 */
9010 if ((baseType != NULL) && (!baseIsAnyType) &&
9011 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9012 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
9013 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAS_ERR_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009014 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009015 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009016 baseType->name, NULL);
9017 }
9018 return (0);
9019}
9020
9021/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009022 * xmlSchemaTypeFinalContains:
9023 * @schema: the schema
9024 * @type: the type definition
9025 * @final: the final
9026 *
9027 * Evaluates if a type definition contains the given "final".
9028 * This does take "finalDefault" into account as well.
9029 *
9030 * Returns 1 if the type does containt the given "final",
9031 * 0 otherwise.
9032 */
9033static int
9034xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
9035{
9036 int tfinal = final, tflags = type->flags;
9037
9038 if (type == NULL)
9039 return (0);
9040 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
9041 switch (final) {
9042 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
9043 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9044 break;
9045 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
9046 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9047 break;
9048 case XML_SCHEMAS_TYPE_FINAL_LIST:
9049 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
9050 break;
9051 case XML_SCHEMAS_TYPE_FINAL_UNION:
9052 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
9053 break;
9054 }
9055 tflags = schema->flags;
9056 }
9057 if (tflags & tfinal)
9058 return (1);
9059 else
9060 return (0);
9061
9062}
9063
9064/**
9065 * xmlSchemaGetUnionSimpleTypeMemberTypes:
9066 * @type: the Union Simple Type
9067 *
9068 * Returns a list of member types of @type if existing,
9069 * returns NULL otherwise.
9070 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009071static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +00009072xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
9073{
9074 while (type != NULL) {
9075 if (type->memberTypes != NULL)
9076 return (type->memberTypes);
9077 else
9078 type = type->baseType;
9079 }
9080 return (NULL);
9081}
9082
9083/**
9084 * xmlSchemaGetListSimpleTypeItemType:
9085 * @type: the simple type definition
9086 *
9087 * Returns the item type definition of the list simple type.
9088 */
9089static xmlSchemaTypePtr
9090xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
9091{
9092 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
9093 return (NULL);
9094 /*
9095 * Note: In libxml2, the built-in types do not reflect
9096 * the datatype hierarchy (yet?) - we have to treat them
9097 * in a special way.
9098 */
9099 if (type->type == XML_SCHEMA_TYPE_BASIC)
9100 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
9101 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
9102 /* 1 If the <list> alternative is chosen, then the type
9103 * definition ·resolved· to by the ·actual value· of the
9104 * itemType [attribute] of <list>, if present, otherwise
9105 * the type definition corresponding to the <simpleType>
9106 * among the [children] of <list>.
9107 */
9108 return (type->subtypes->subtypes);
9109 else {
9110 /* 2 If the <restriction> option is chosen, then the
9111 * {item type definition} of the {base type definition}.
9112 */
9113 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
9114 }
9115}
9116
9117/**
9118 * xmlSchemaCheckCOSSTDerivedOK:
9119 * @type: the derived simple type definition
9120 * @baseType: the base type definition
9121 *
9122 * Checks wheter @type can be validly
9123 * derived from @baseType.
9124 *
9125 * Returns 0 on success, an positive error code otherwise.
9126 */
9127static int
9128xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
9129 xmlSchemaTypePtr type,
9130 xmlSchemaTypePtr baseType,
9131 int subset)
9132{
9133 /*
9134 * Schema Component Constraint: Type Derivation OK (Simple)
9135 *
9136 *
9137 * 1 They are the same type definition.
9138 * TODO: The identy check might have to be more complex than this.
9139 */
9140 if (type == baseType)
9141 return (0);
9142 /*
9143 * 2.1 restriction is not in the subset, or in the {final}
9144 * of its own {base type definition};
9145 */
9146 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
9147 (xmlSchemaTypeFinalContains(schema,
9148 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
9149 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
9150 }
9151 /* 2.2 */
9152 if (type->baseType == baseType) {
9153 /*
9154 * 2.2.1 D's ·base type definition· is B.
9155 */
9156 return (0);
9157 }
9158 /*
9159 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
9160 * and is validly derived from B given the subset, as defined by this
9161 * constraint.
9162 */
9163 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
9164 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
9165 return (0);
9166 }
9167 /*
9168 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
9169 * definition·.
9170 */
9171 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
9172 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
9173 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
9174 return (0);
9175 }
9176 /*
9177 * 2.2.4 B's {variety} is union and D is validly derived from a type
9178 * definition in B's {member type definitions} given the subset, as
9179 * defined by this constraint.
9180 *
9181 * NOTE: This seems not to involve built-in types, since there is no
9182 * built-in Union Simple Type.
9183 */
9184 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9185 xmlSchemaTypeLinkPtr cur;
9186
9187 cur = baseType->memberTypes;
9188 while (cur != NULL) {
9189 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
9190 cur->type, subset) == 0)
9191 return (0);
9192 cur = cur->next;
9193 }
9194 }
9195
9196 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
9197}
9198
9199
9200/**
9201 * xmlSchemaCheckSTPropsCorrect:
9202 * @ctxt: the schema parser context
9203 * @type: the simple type definition
9204 *
9205 * Checks st-props-correct.
9206 *
9207 * Returns 0 if the properties are correct,
9208 * if not, a positive error code and -1 on internal
9209 * errors.
9210 */
9211static int
9212xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
9213 xmlSchemaTypePtr type)
9214{
9215 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
9216 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009217 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009218
Daniel Veillardc0826a72004-08-10 14:17:33 +00009219 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009220 /*
9221 * Schema Component Constraint: Simple Type Definition Properties Correct
9222 *
9223 * NOTE: This is somehow redundant, since we actually built a simple type
9224 * to have all the needed information; this acts as an self test.
9225 */
9226 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9227 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9228 /*
9229 * TODO: 1 The values of the properties of a simple type definition must be as
9230 * described in the property tableau in Datatype definition, modulo the
9231 * impact of Missing Sub-components (§5.3).
9232 */
9233 /* Base type: If the datatype has been ·derived· by ·restriction·
9234 * then the Simple Type Definition component from which it is ·derived·,
9235 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
9236 */
9237 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009238 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009239 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009240 NULL, type, NULL,
9241 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009242 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9243 }
9244 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
9245 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
9246 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009247 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009248 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009249 NULL, type, NULL,
9250 "The base type %s is not a simple type",
9251 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9252 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009253 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9254 }
9255 if ((baseType != anySimpleType) &&
9256 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009257 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009258 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009259 NULL, type, NULL,
9260 "A type, derived by list or union, must have"
9261 "the simple ur-type definition as base type, not %s",
9262 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9263 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009264 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9265 }
9266 /*
9267 * Variety: One of {atomic, list, union}.
9268 */
9269 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9270 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
9271 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009272 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009273 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009274 NULL, type, NULL,
9275 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009276 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
9277 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009278 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009279
9280 /*
9281 * 2 All simple type definitions must be derived ultimately from the ·simple
9282 * ur-type definition (so· circular definitions are disallowed). That is, it
9283 * must be possible to reach a built-in primitive datatype or the ·simple
9284 * ur-type definition· by repeatedly following the {base type definition}.
9285 */
9286 baseType = type->baseType;
9287 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
9288 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9289 xmlSchemaTypeFixup(baseType, ctxt, NULL);
9290 if (baseType == anySimpleType)
9291 break;
9292 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009293 xmlSchemaPCustomErr(ctxt,
9294 XML_SCHEMAP_ST_PROPS_CORRECT_2,
9295 NULL, type, NULL,
9296 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009297 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
9298 }
9299 baseType = baseType->baseType;
9300 }
9301 /*
9302 * 3 The {final} of the {base type definition} must not contain restriction.
9303 */
9304 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
9305 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009306 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009307 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009308 NULL, type, NULL,
9309 "The 'final' of its base type %s must not contain "
9310 "'restriction'",
9311 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9312 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009313 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
9314 }
9315 return (0);
9316}
9317
9318/**
9319 * xmlSchemaCheckDerivationValidSimpleRestriction:
9320 * @ctxt: the schema parser context
9321 * @type: the simple type definition
9322 *
9323 * Checks if the given @type (simpleType) is derived
9324 * validly by restriction.
9325 *
9326 * Returns -1 on internal errors, 0 if the type is validly derived,
9327 * a positive error code otherwise.
9328 */
9329static int
9330xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009331 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009332{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009333 xmlChar *str = NULL;
9334
9335 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009336
9337 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
9338 xmlSchemaPErr(ctxt, type->node,
9339 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009340 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
9341 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009342 type->name, NULL);
9343 return (-1);
9344 }
9345
9346 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
9347 xmlSchemaTypePtr primitive;
9348 /*
9349 * 1.1 The {base type definition} must be an atomic simple
9350 * type definition or a built-in primitive datatype.
9351 */
9352 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009353 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009354 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009355 NULL, type, NULL,
9356 "The base type %s is not an atomic simple type",
9357 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9358 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009359 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
9360 }
9361 /* 1.2 The {final} of the {base type definition} must not contain
9362 * restriction.
9363 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009364 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009365 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
9366 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009367 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009368 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009369 NULL, type, NULL,
9370 "The final of its base type %s must not contain 'restriction'",
9371 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9372 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009373 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
9374 }
9375
9376 /*
9377 * 1.3.1 DF must be an allowed constraining facet for the {primitive
9378 * type definition}, as specified in the appropriate subsection of 3.2
9379 * Primitive datatypes.
9380 */
9381 if (type->facets != NULL) {
9382 xmlSchemaFacetPtr facet;
9383 int ok = 1;
9384
9385 primitive = xmlSchemaGetPrimitiveType(type);
9386 if (primitive == NULL) {
9387 xmlSchemaPErr(ctxt, type->node,
9388 XML_ERR_INTERNAL_ERROR,
9389 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009390 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009391 type->name, NULL);
9392 return (-1);
9393 }
9394 facet = type->facets;
9395 do {
9396 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009397 ok = 0;
9398 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009399 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009400 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009401 }
9402 facet = facet->next;
9403 } while (facet != NULL);
9404 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00009405 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009406 }
9407 /*
9408 * TODO: 1.3.2 (facet derivation)
9409 */
9410 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
9411 xmlSchemaTypePtr itemType = NULL;
9412
9413 itemType = xmlSchemaGetListSimpleTypeItemType(type);
9414 if (itemType == NULL) {
9415 xmlSchemaPErr(ctxt, type->node,
9416 XML_ERR_INTERNAL_ERROR,
9417 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009418 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009419 type->name, NULL);
9420 return (-1);
9421 }
9422 /*
9423 * 2.1 The {item type definition} must have a {variety} of atomic or
9424 * union (in which case all the {member type definitions}
9425 * must be atomic).
9426 */
9427 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9428 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009429 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009430 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009431 NULL, type, NULL,
9432 "The item type %s must have a variety of atomic or union",
9433 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
9434 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009435 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
9436 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9437 xmlSchemaTypeLinkPtr member;
9438
9439 member = itemType->memberTypes;
9440 while (member != NULL) {
9441 if ((member->type->flags &
9442 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009443 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009444 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009445 NULL, type, NULL,
9446 "The item type is a union type, but the "
9447 "member type %s of this item type is not atomic",
9448 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
9449 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009450 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
9451 }
9452 member = member->next;
9453 }
9454 }
9455
9456 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
9457 xmlSchemaFacetPtr facet;
9458 /*
9459 * This is the case if we have: <simpleType><list ..
9460 */
9461 /*
9462 * 2.3.1
9463 * 2.3.1.1 The {final} of the {item type definition} must not
9464 * contain list.
9465 */
9466 if (xmlSchemaTypeFinalContains(ctxt->schema,
9467 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009469 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009470 NULL, type, NULL,
9471 "The final of its item type %s must not contain 'list'",
9472 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
9473 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009474 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
9475 }
9476 /*
9477 * 2.3.1.2 The {facets} must only contain the whiteSpace
9478 * facet component.
9479 */
9480 if (type->facets != NULL) {
9481 facet = type->facets;
9482 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009483 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
9484 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009485 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009486 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009487 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
9488 }
9489 facet = facet->next;
9490 } while (facet != NULL);
9491 }
9492 /*
9493 * TODO: Datatypes states:
9494 * A ·list· datatype can be ·derived· from an ·atomic· datatype
9495 * whose ·lexical space· allows space (such as string or anyURI)or
9496 * a ·union· datatype any of whose {member type definitions}'s
9497 * ·lexical space· allows space.
9498 */
9499 } else {
9500 /*
9501 * This is the case if we have: <simpleType><restriction ...
9502 */
9503 /*
9504 * 2.3.2
9505 * 2.3.2.1 The {base type definition} must have a {variety} of list.
9506 */
9507 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009508 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009509 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009510 NULL, type, NULL,
9511 "The base type %s must be a list type",
9512 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9513 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009514 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
9515 }
9516 /*
9517 * 2.3.2.2 The {final} of the {base type definition} must not
9518 * contain restriction.
9519 */
9520 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
9521 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009522 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009523 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 NULL, type, NULL,
9525 "The final of the base type %s must not contain 'restriction'",
9526 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9527 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009528 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
9529 }
9530 /*
9531 * 2.3.2.3 The {item type definition} must be validly derived
9532 * from the {base type definition}'s {item type definition} given
9533 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
9534 */
9535 {
9536 xmlSchemaTypePtr baseItemType;
9537
9538 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
9539 if (baseItemType == NULL) {
9540 xmlSchemaPErr(ctxt, type->node,
9541 XML_ERR_INTERNAL_ERROR,
9542 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009543 "List simple type '%s': Failed to "
9544 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009545 type->name, type->baseType->name);
9546 return (-1);
9547 }
9548 if ((itemType != baseItemType) &&
9549 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
9550 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009551 xmlChar *strBIT = NULL, *strBT = NULL;
9552 xmlSchemaPCustomErrExt(ctxt,
9553 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
9554 NULL, type, NULL,
9555 "The item type %s is not validly derived from the "
9556 "item type %s of the base type %s",
9557 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
9558 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
9559 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
9560
9561 FREE_AND_NULL(str)
9562 FREE_AND_NULL(strBIT)
9563 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009564 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
9565 }
9566 }
9567
9568 if (type->facets != NULL) {
9569 xmlSchemaFacetPtr facet;
9570 int ok = 1;
9571 /*
9572 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
9573 * and enumeration facet components are allowed among the {facets}.
9574 */
9575 facet = type->facets;
9576 do {
9577 switch (facet->type) {
9578 case XML_SCHEMA_FACET_LENGTH:
9579 case XML_SCHEMA_FACET_MINLENGTH:
9580 case XML_SCHEMA_FACET_MAXLENGTH:
9581 case XML_SCHEMA_FACET_WHITESPACE:
9582 /*
9583 * TODO: 2.5.1.2 List datatypes
9584 * The value of ·whiteSpace· is fixed to the value collapse.
9585 */
9586 case XML_SCHEMA_FACET_PATTERN:
9587 case XML_SCHEMA_FACET_ENUMERATION:
9588 break;
9589 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009590 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009591 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009592 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009593 /*
9594 * We could return, but it's nicer to report all
9595 * invalid facets.
9596 */
9597 ok = 0;
9598 }
9599 }
9600 facet = facet->next;
9601 } while (facet != NULL);
9602 if (ok == 0)
9603 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
9604 /*
9605 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
9606 * is a facet of the same kind in the {facets} of the {base type
9607 * definition} (call this BF),then the DF's {value} must be a valid
9608 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
9609 */
9610 }
9611
9612
9613 }
9614 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9615 /*
9616 * 3.1 The {member type definitions} must all have {variety} of
9617 * atomic or list.
9618 */
9619 xmlSchemaTypeLinkPtr member;
9620
9621 member = type->memberTypes;
9622 while (member != NULL) {
9623 if (((member->type->flags &
9624 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
9625 ((member->type->flags &
9626 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009627 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009628 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009629 NULL, type, NULL,
9630 "The member type %s is neither an atomic, nor a list type",
9631 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
9632 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009633 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
9634 }
9635 member = member->next;
9636 }
9637 /*
9638 * 3.3.1 If the {base type definition} is the ·simple ur-type
9639 * definition·
9640 */
9641 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
9642 /*
9643 * 3.3.1.1 All of the {member type definitions} must have a
9644 * {final} which does not contain union.
9645 */
9646 member = type->memberTypes;
9647 while (member != NULL) {
9648 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
9649 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009650 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009651 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009652 NULL, type, NULL,
9653 "The final of member type %s contains 'union'",
9654 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
9655 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009656 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
9657 }
9658 member = member->next;
9659 }
9660 /*
9661 * 3.3.1.2 The {facets} must be empty.
9662 */
9663 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009664 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009665 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009666 NULL, type, NULL,
9667 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009668 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
9669 }
9670 } else {
9671 /*
9672 * 3.3.2.1 The {base type definition} must have a {variety} of union.
9673 */
9674 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009675 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009676 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009677 NULL, type, NULL,
9678 "The base type %s is not a union type",
9679 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9680 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009681 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
9682 }
9683 /*
9684 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
9685 */
9686 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
9687 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009688 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009689 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009690 NULL, type, NULL,
9691 "The final of its base type %s must not contain 'restriction'",
9692 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
9693 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009694 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
9695 }
9696 /*
9697 * 3.3.2.3 The {member type definitions}, in order, must be validly
9698 * derived from the corresponding type definitions in the {base
9699 * type definition}'s {member type definitions} given the empty set,
9700 * as defined in Type Derivation OK (Simple) (§3.14.6).
9701 */
9702 {
9703 xmlSchemaTypeLinkPtr baseMember;
9704
9705 /*
9706 * OPTIMIZE: if the type is restricting, it has no local defined
9707 * member types and inherits the member types of the base type;
9708 * thus a check for equality can be skipped.
9709 */
9710 /*
9711 * TODO: Even worse: I cannot see a scenario where a restricting
9712 * union simple type can have other member types as the member
9713 * types of it's base type. This check seems not necessary with
9714 * respect to the derivation process in libxml2.
9715 */
9716 if (type->memberTypes != NULL) {
9717 member = type->memberTypes;
9718 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
9719 if ((member == NULL) && (baseMember != NULL)) {
9720 xmlSchemaPErr(ctxt, type->node,
9721 XML_SCHEMAS_ERR_INTERNAL,
9722 "Internal error: "
9723 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009724 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +00009725 "of member types in the base type\n",
9726 type->name, NULL);
9727 }
9728 while (member != NULL) {
9729 if (baseMember == NULL) {
9730 xmlSchemaPErr(ctxt, type->node,
9731 XML_SCHEMAS_ERR_INTERNAL,
9732 "Internal error: "
9733 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009734 "(3.3.2.3), union simple type '%s', unequal number "
9735 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009736 type->name, NULL);
9737 }
9738 if ((member->type != baseMember->type) &&
9739 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
9740 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009741 xmlChar *strBMT = NULL, *strBT = NULL;
9742
9743 xmlSchemaPCustomErrExt(ctxt,
9744 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
9745 NULL, type, NULL,
9746 "The member type %s is not validly derived from its "
9747 "corresponding member type %s of the base type %s",
9748 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
9749 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
9750 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
9751 FREE_AND_NULL(str)
9752 FREE_AND_NULL(strBMT)
9753 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009754 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
9755 }
9756 member = member->next;
9757 baseMember = baseMember->next;
9758 }
9759 }
9760 }
9761 /*
9762 * 3.3.2.4 Only pattern and enumeration facet components are
9763 * allowed among the {facets}.
9764 */
9765 if (type->facets != NULL) {
9766 xmlSchemaFacetPtr facet;
9767 int ok = 1;
9768
9769 facet = type->facets;
9770 do {
9771 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
9772 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009773 xmlSchemaPIllegalFacetListUnionErr(ctxt,
9774 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
9775 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009776 ok = 0;
9777 }
9778 facet = facet->next;
9779 } while (facet != NULL);
9780 if (ok == 0)
9781 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
9782
9783 }
9784 /*
9785 * TODO: 3.3.2.5 (facet derivation)
9786 */
9787 }
9788 }
9789
9790 return (0);
9791}
9792
9793/**
9794 * xmlSchemaCheckSRCSimpleType:
9795 * @ctxt: the schema parser context
9796 * @type: the simple type definition
9797 *
9798 * Checks crc-simple-type constraints.
9799 *
9800 * Returns 0 if the constraints are satisfied,
9801 * if not a positive error code and -1 on internal
9802 * errors.
9803 */
9804static int
9805xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
9806 xmlSchemaTypePtr type)
9807{
9808 /*
9809 * NOTE: src-simple-type 2-4 are redundant, since the checks
9810 * were are done for the corresponding <restriction>, <list> and <union>
9811 * elements, but W3C wants a <simpleType> error as well, so it gets one.
9812 * Maby this can be skipped in the future, if we get sure it's not needed.
9813 */
9814 if (type->subtypes == NULL) {
9815 xmlSchemaPErr(ctxt, type->node,
9816 XML_SCHEMAS_ERR_INTERNAL,
9817 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009818 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009819 type->name, NULL);
9820 return (-1);
9821 }
9822 /*
9823 * src-simple-type.1 The corresponding simple type definition, if any,
9824 * must satisfy the conditions set out in Constraints on Simple Type
9825 * Definition Schema Components (§3.14.6).
9826 */
9827 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
9828 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
9829 /*
9830 * TODO: Removed this, since it got annoying to get an
9831 * extra error report, if anything failed until now.
9832 * Enable this if needed.
9833 */
9834 /*
9835 xmlSchemaPErr(ctxt, type->node,
9836 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009837 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +00009838 "on simple type definitions.\n",
9839 type->name, NULL);
9840 */
9841 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
9842 }
9843
9844 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
9845 /*
9846 * src-simple-type.2 If the <restriction> alternative is chosen,
9847 * either it must have a base [attribute] or a <simpleType> among its
9848 * [children], but not both.
9849 */
9850 if (((type->subtypes->base == NULL) &&
9851 ((type->subtypes->subtypes == NULL) ||
9852 (type->subtypes->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
9853 ((type->subtypes->base != NULL) &&
9854 (type->subtypes->subtypes != NULL) &&
9855 (type->subtypes->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009856 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009857 XML_SCHEMAP_SRC_SIMPLE_TYPE_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009858 NULL, type, NULL,
9859 "Either the attribute 'base' or the <simpleType> child "
9860 "must be present on the <restriction> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009861 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_2);
9862 }
9863 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
9864 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
9865 * an itemType [attribute] or a <simpleType> among its [children],
9866 * but not both.
9867 * NOTE: baseType is set to the local simple type definiton,
9868 * if existent, at parse time. This is a hack and not nice.
9869 */
9870 if (((type->subtypes->base == NULL) &&
9871 (type->baseType == NULL)) ||
9872 ((type->subtypes->base != NULL) &&
9873 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009874 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009875 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009876 NULL, type, NULL,
9877 "Either the attribute 'itemType' or the <simpleType> child "
9878 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009879 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
9880 }
9881
9882
9883 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
9884 xmlSchemaTypeLinkPtr member;
9885 xmlSchemaTypePtr ancestor, anySimpleType;
9886
9887 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9888
9889 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
9890 * the <union> alternative is chosen, there must not be any entries
9891 * in the memberTypes [attribute] at any depth which resolve to the
9892 * component corresponding to the <simpleType>.
9893 */
9894 member = type->memberTypes;
9895 while (member != NULL) {
9896 ancestor = member->type;
9897 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
9898 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9899 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
9900 if (ancestor == anySimpleType)
9901 break;
9902 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009903 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009904 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009905 NULL, type, NULL,
9906 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009907 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
9908 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
9909 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00009910 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +00009911 * type as item type, which in turn has a list ST as member
9912 * type, we will assume this here as well, since this check
9913 * was not yet performed.
9914 */
9915
9916 }
9917 ancestor = ancestor->baseType;
9918 }
9919 member = member->next;
9920 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009921 }
9922
9923 return (0);
9924}
9925
9926/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009927 * xmlSchemaTypeFixup:
9928 * @typeDecl: the schema type definition
9929 * @ctxt: the schema parser context
9930 *
9931 * Fixes the content model of the type.
9932 */
9933static void
9934xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009935 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00009936{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009937 xmlSchemaTypePtr ctxtType;
9938
Daniel Veillard82bbbd42003-05-11 20:16:09 +00009939 if (typeDecl == NULL)
9940 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009941 /*
9942 * Do not allow the following types to be typefixed, prior to
9943 * the corresponding simple/complex types.
9944 */
9945 if (ctxt->ctxtType == NULL) {
9946 switch (typeDecl->type) {
9947 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9948 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9949 case XML_SCHEMA_TYPE_UNION:
9950 case XML_SCHEMA_TYPE_RESTRICTION:
9951 case XML_SCHEMA_TYPE_EXTENSION:
9952 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009953 default:
9954 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009955 }
9956 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009957 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009958 name = typeDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009959 if (typeDecl->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009960 switch (typeDecl->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009961 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
9962 if (typeDecl->subtypes != NULL) {
9963 if (typeDecl->subtypes->contentType ==
9964 XML_SCHEMA_CONTENT_UNKNOWN) {
9965 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
9966 NULL);
9967 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009968 typeDecl->contentType =
9969 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009970 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009971 break;
9972 }
9973 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009974 xmlSchemaTypePtr base = NULL;
9975
9976 ctxt->ctxtType->flags |=
9977 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009978 if (typeDecl->subtypes != NULL)
9979 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009980
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009981 if (typeDecl->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009982 base =
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009983 xmlSchemaGetType(ctxt->schema, typeDecl->base,
9984 typeDecl->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009985 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009986 xmlSchemaPResCompAttrErr(ctxt,
9987 XML_SCHEMAP_SRC_RESOLVE,
9988 NULL, typeDecl, typeDecl->node,
9989 "base", typeDecl->base, typeDecl->baseNs,
9990 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009991 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +00009992 XML_SCHEMA_CONTENT_UNKNOWN) {
9993 /*
9994 * The base type might be not "type fixed" yet,
9995 * so do it now. */
9996 /*
9997 * TODO: Is a check for circular derivation already
9998 * done?
9999 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010000 xmlSchemaTypeFixup(base, ctxt, NULL);
10001 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010002 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010003 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
10004 /*
10005 * ComplexType restriction.
10006 */
10007 /*
10008 * Base type: The type definition ·resolved· to by the ·actual
10009 * value· of the base [attribute]
10010 */
10011 ctxt->ctxtType->baseType = base;
10012 /*
10013 * Content type.
10014 */
10015 if (typeDecl->subtypes == NULL)
10016 /* 1.1.1 */
10017 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10018 else if ((typeDecl->subtypes->subtypes == NULL) &&
10019 ((typeDecl->subtypes->type ==
10020 XML_SCHEMA_TYPE_ALL)
10021 || (typeDecl->subtypes->type ==
10022 XML_SCHEMA_TYPE_SEQUENCE)))
10023 /* 1.1.2 */
10024 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10025 else if ((typeDecl->subtypes->type ==
10026 XML_SCHEMA_TYPE_CHOICE)
10027 && (typeDecl->subtypes->subtypes == NULL))
10028 /* 1.1.3 */
10029 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
10030 else {
10031 /* 1.2 and 2.X are applied at the other layer */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010032 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000010033 XML_SCHEMA_CONTENT_ELEMENTS;
10034 }
10035 } else {
10036 /*
10037 * SimpleType restriction.
10038 */
10039 /* Base type:
10040 * The Simple Type Definition component resolved to by
10041 * the actual value of the base [attribute] or the
10042 * <simpleType> [children], whichever is present.
10043 */
10044 if ((base == NULL) && (typeDecl->subtypes != NULL)) {
10045 base = typeDecl->subtypes;
10046 ctxt->ctxtType->baseType = base;
10047 if (base->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10048 xmlSchemaTypeFixup(base, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010049 } else
Daniel Veillard01fa6152004-06-29 17:04:39 +000010050 ctxt->ctxtType->baseType = base;
10051
10052 if (((typeDecl->base == NULL) &&
10053 ((typeDecl->subtypes == NULL) ||
10054 (typeDecl->subtypes->type != XML_SCHEMA_TYPE_SIMPLE))) ||
10055 ((typeDecl->base != NULL) &&
10056 (typeDecl->subtypes != NULL) &&
10057 (typeDecl->subtypes->type == XML_SCHEMA_TYPE_SIMPLE))) {
10058 /*
10059 * src-restriction-base-or-simpleType
10060 * Either the base [attribute] or the simpleType [child] of the
10061 * <restriction> element must be present, but not both.
Daniel Veillardc0826a72004-08-10 14:17:33 +000010062 * TODO: Move this to the parse function.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010063 */
10064 xmlSchemaPErr(ctxt, typeDecl->node,
10065 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010066 "<restriction>: "
10067 "Either the 'base' attribute or the <simpleType> child "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010068 "must be present, but not both.\n",
10069 typeDecl->name, NULL);
10070 }
10071 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010072 break;
10073 }
10074 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000010075 xmlSchemaTypePtr base = NULL;
10076 xmlSchemaContentType explicitContentType;
10077
10078 /*
10079 * An extension does exist on a complexType only.
10080 */
10081 ctxt->ctxtType->flags |=
10082 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
10083 if (typeDecl->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010084 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010085 xmlSchemaPCustomErr(ctxt,
10086 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10087 NULL, typeDecl, typeDecl->node,
10088 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000010089 return;
10090 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010091 if (typeDecl->base != NULL) {
10092 base =
10093 xmlSchemaGetType(ctxt->schema, typeDecl->base,
10094 typeDecl->baseNs);
10095 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010096 xmlSchemaPResCompAttrErr(ctxt,
10097 XML_SCHEMAP_SRC_RESOLVE,
10098 NULL, typeDecl, typeDecl->node,
10099 "base", typeDecl->base, typeDecl->baseNs,
10100 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010101 } else if (base->contentType ==
10102 XML_SCHEMA_CONTENT_UNKNOWN) {
10103 typeDecl->recurse = 1;
10104 xmlSchemaTypeFixup(base, ctxt, NULL);
10105 typeDecl->recurse = 0;
10106 }
10107 /*
10108 * The type definition ·resolved· to by the ·actual
10109 * value· of the base [attribute]
10110 */
10111 ctxt->ctxtType->baseType = base;
10112 /*
10113 * TODO: This one is still needed for computation of
10114 * the content model by xmlSchemaBuildAContentModel.
10115 * Try to get rid of it.
10116 */
10117 typeDecl->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010118 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010119 if ((typeDecl->subtypes != NULL) &&
10120 (typeDecl->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10121 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
10122
10123 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
10124 if (typeDecl->subtypes == NULL)
10125 /* 1.1.1 */
10126 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
10127 else if ((typeDecl->subtypes->subtypes == NULL) &&
10128 ((typeDecl->subtypes->type ==
10129 XML_SCHEMA_TYPE_ALL)
10130 || (typeDecl->subtypes->type ==
10131 XML_SCHEMA_TYPE_SEQUENCE)))
10132 /* 1.1.2 */
10133 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
10134 else if ((typeDecl->subtypes->type ==
10135 XML_SCHEMA_TYPE_CHOICE)
10136 && (typeDecl->subtypes->subtypes == NULL))
10137 /* 1.1.3 */
10138 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
10139 if (base != NULL) {
10140 /* It will be reported later, if the base is missing. */
10141 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
10142 /* 2.1 */
10143 typeDecl->contentType = base->contentType;
10144 } else if (base->contentType ==
10145 XML_SCHEMA_CONTENT_EMPTY) {
10146 /* 2.2 imbitable ! */
10147 typeDecl->contentType =
10148 XML_SCHEMA_CONTENT_ELEMENTS;
10149 } else {
10150 /* 2.3 imbitable pareil ! */
10151 typeDecl->contentType =
10152 XML_SCHEMA_CONTENT_ELEMENTS;
10153 }
10154 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010155 break;
10156 }
10157 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010158 ctxtType = ctxt->ctxtType;
10159 ctxt->ctxtType = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010160 if ((typeDecl->subtypes == NULL) ||
10161 ((typeDecl->subtypes->type !=
10162 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
10163 (typeDecl->subtypes->type !=
10164 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
10165 /*
10166 * This case is understood as shorthand for complex
10167 * content restricting the ur-type definition, and
10168 * the details of the mappings should be modified as
10169 * necessary.
10170 */
10171 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10172 typeDecl->flags |=
10173 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
10174 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010175 if (typeDecl->subtypes == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010176 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000010177 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
10178 typeDecl->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000010179 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010180 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010181 if ((typeDecl->subtypes != NULL) &&
10182 (typeDecl->subtypes->contentType ==
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010183 XML_SCHEMA_CONTENT_UNKNOWN)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010184 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010185 NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010186 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010187 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010188 typeDecl->contentType =
10189 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010190 } else {
10191 if (typeDecl->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010192 typeDecl->contentType =
10193 typeDecl->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010194 }
10195 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010196 }
10197 xmlSchemaBuildAttributeValidation(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010198 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010199 break;
10200 }
10201 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
10202 if (typeDecl->subtypes == NULL) {
10203 typeDecl->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard1aefc862004-03-04 11:40:48 +000010204 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED)
10205 typeDecl->contentType =
10206 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010207 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000010208 if (typeDecl->flags & XML_SCHEMAS_TYPE_MIXED) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010209 typeDecl->contentType =
10210 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000010211 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010212 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt,
10213 NULL);
10214 if (typeDecl->subtypes != NULL)
10215 typeDecl->contentType =
10216 typeDecl->subtypes->contentType;
10217 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010218 /*
10219 * Removed due to implementation of the build of attribute uses.
10220 */
10221 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000010222 if (typeDecl->attributes == NULL)
10223 typeDecl->attributes =
10224 typeDecl->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000010225 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010226 }
10227 break;
10228 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010229 case XML_SCHEMA_TYPE_SIMPLE:
10230 /*
10231 * Simple Type Definition Schema Component
10232 *
10233 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010234 ctxtType = ctxt->ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010235 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10236 if (typeDecl->subtypes->contentType ==
10237 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010238 ctxt->ctxtType = typeDecl;
10239 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010240 }
10241 /* Fixup base type */
10242 if ((typeDecl->baseType != NULL) &&
10243 (typeDecl->baseType->contentType ==
10244 XML_SCHEMA_CONTENT_UNKNOWN)) {
10245 /* OPTIMIZE: Actually this one will never by hit, since
10246 * the base type is already type-fixed in <restriction>.
10247 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010248 ctxt->ctxtType = typeDecl;
10249 xmlSchemaTypeFixup(typeDecl->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010250 }
10251 /* Base type:
10252 * 2 If the <list> or <union> alternative is chosen,
10253 * then the ·simple ur-type definition·.
10254 */
10255 if (typeDecl->subtypes->type ==
10256 XML_SCHEMA_TYPE_LIST) {
10257 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10258 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
10259 } else if (typeDecl->subtypes->type ==
10260 XML_SCHEMA_TYPE_UNION) {
10261 typeDecl->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10262 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
10263 } else if (typeDecl->subtypes->type ==
10264 XML_SCHEMA_TYPE_RESTRICTION) {
10265 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
10266
10267 /*
10268 * Variety
10269 * If the <restriction> alternative is chosen, then the
10270 * {variety} of the {base type definition}.
10271 */
10272 if (typeDecl->baseType != NULL) {
10273 if (typeDecl->baseType->flags &
10274 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
10275 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
10276 else if (typeDecl->baseType->flags &
10277 XML_SCHEMAS_TYPE_VARIETY_LIST)
10278 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
10279 else if (typeDecl->baseType->flags &
10280 XML_SCHEMAS_TYPE_VARIETY_UNION)
10281 typeDecl->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
10282 /*
10283 * Schema Component Constraint: Simple Type Restriction
10284 * (Facets)
10285 * NOTE: Satisfaction of 1 and 2 arise from the fixup
10286 * applied beforehand.
10287 *
10288 * 3 The {facets} of R are the union of S and the {facets}
10289 * of B, eliminating duplicates. To eliminate duplicates,
10290 * when a facet of the same kind occurs in both S and the
10291 * {facets} of B, the one in the {facets} of B is not
10292 * included, with the exception of enumeration and pattern
10293 * facets, for which multiple occurrences with distinct values
10294 * are allowed.
10295 */
10296 if (typeDecl->baseType->facetSet != NULL) {
10297 last = typeDecl->facetSet;
10298 if (last != NULL)
10299 while (last->next != NULL)
10300 last = last->next;
10301 cur = typeDecl->baseType->facetSet;
10302 for (; cur != NULL; cur = cur->next) {
10303 /*
10304 * Base patterns won't be add here:
10305 * they are ORed in a type and
10306 * ANDed in derived types. This will
10307 * happed at validation level by
10308 * walking the base axis of the type.
10309 */
10310 if (cur->facet->type ==
10311 XML_SCHEMA_FACET_PATTERN)
10312 continue;
10313 facet = NULL;
10314 if ((typeDecl->facetSet != NULL) &&
10315 (cur->facet->type !=
10316 XML_SCHEMA_FACET_PATTERN) &&
10317 (cur->facet->type !=
10318 XML_SCHEMA_FACET_ENUMERATION)) {
10319 facet = typeDecl->facetSet;
10320 do {
10321 if (cur->facet->type ==
10322 facet->facet->type)
10323 break;
10324 facet = facet->next;
10325 } while (facet != NULL);
10326 }
10327 if (facet == NULL) {
10328 facet = (xmlSchemaFacetLinkPtr)
10329 xmlMalloc(sizeof(xmlSchemaFacetLink));
10330 if (facet == NULL) {
10331 xmlSchemaPErrMemory(ctxt,
10332 "fixing simpleType", NULL);
10333 return;
10334 }
10335 facet->facet = cur->facet;
10336 facet->next = NULL;
10337 if (last == NULL)
10338 typeDecl->facetSet = facet;
10339 else
10340 last->next = facet;
10341 last = facet;
10342 }
10343 }
10344 }
10345 }
10346 }
10347 /*
10348 * Check constraints.
10349 */
10350 xmlSchemaCheckSRCSimpleType(ctxt, typeDecl);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000010351 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010352 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010353 case XML_SCHEMA_TYPE_SEQUENCE:
10354 case XML_SCHEMA_TYPE_GROUP:
10355 case XML_SCHEMA_TYPE_ALL:
10356 case XML_SCHEMA_TYPE_CHOICE:
10357 typeDecl->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
10358 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010359 case XML_SCHEMA_TYPE_LIST:
Daniel Veillard3646d642004-06-02 19:19:14 +000010360 xmlSchemaParseListRefFixup(typeDecl, ctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010361 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10362 break;
10363 case XML_SCHEMA_TYPE_UNION:
10364 xmlSchemaParseUnionRefCheck(typeDecl, ctxt);
10365 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10366 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010367 case XML_SCHEMA_TYPE_BASIC:
10368 case XML_SCHEMA_TYPE_ANY:
10369 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010370 case XML_SCHEMA_TYPE_UR:
10371 case XML_SCHEMA_TYPE_ELEMENT:
10372 case XML_SCHEMA_TYPE_ATTRIBUTE:
10373 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000010374 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010375 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010376 case XML_SCHEMA_FACET_MININCLUSIVE:
10377 case XML_SCHEMA_FACET_MINEXCLUSIVE:
10378 case XML_SCHEMA_FACET_MAXINCLUSIVE:
10379 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
10380 case XML_SCHEMA_FACET_TOTALDIGITS:
10381 case XML_SCHEMA_FACET_FRACTIONDIGITS:
10382 case XML_SCHEMA_FACET_PATTERN:
10383 case XML_SCHEMA_FACET_ENUMERATION:
10384 case XML_SCHEMA_FACET_WHITESPACE:
10385 case XML_SCHEMA_FACET_LENGTH:
10386 case XML_SCHEMA_FACET_MAXLENGTH:
10387 case XML_SCHEMA_FACET_MINLENGTH:
10388 typeDecl->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010389 if (typeDecl->subtypes != NULL)
10390 xmlSchemaTypeFixup(typeDecl->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010391 break;
10392 }
10393 }
Daniel Veillard8651f532002-04-17 09:06:27 +000010394#ifdef DEBUG_TYPE
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010395 if (typeDecl->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010396 xmlGenericError(xmlGenericErrorContext,
10397 "Type of %s : %s:%d :", name,
10398 typeDecl->node->doc->URL,
10399 xmlGetLineNo(typeDecl->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010400 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010401 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010402 }
Daniel Veillard8651f532002-04-17 09:06:27 +000010403 switch (typeDecl->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010404 case XML_SCHEMA_CONTENT_SIMPLE:
10405 xmlGenericError(xmlGenericErrorContext, "simple\n");
10406 break;
10407 case XML_SCHEMA_CONTENT_ELEMENTS:
10408 xmlGenericError(xmlGenericErrorContext, "elements\n");
10409 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000010410 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010411 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
10412 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000010413 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010414 xmlGenericError(xmlGenericErrorContext, "empty\n");
10415 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000010416 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010417 xmlGenericError(xmlGenericErrorContext, "mixed\n");
10418 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010419 /* Removed, since not used. */
10420 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000010421 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010422 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
10423 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010424 */
Daniel Veillard8651f532002-04-17 09:06:27 +000010425 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010426 xmlGenericError(xmlGenericErrorContext, "basic\n");
10427 break;
10428 default:
10429 xmlGenericError(xmlGenericErrorContext,
10430 "not registered !!!\n");
10431 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000010432 }
10433#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010434}
10435
10436/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010437 * xmlSchemaCheckFacet:
10438 * @facet: the facet
10439 * @typeDecl: the schema type definition
10440 * @ctxt: the schema parser context or NULL
10441 * @name: name of the type
10442 *
10443 * Checks the default values types, especially for facets
10444 *
10445 * Returns 0 if okay or -1 in cae of error
10446 */
10447int
10448xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010449 xmlSchemaTypePtr typeDecl,
10450 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010451{
10452 static xmlSchemaTypePtr nonNegativeIntegerType = NULL;
10453 int ret = 0;
10454
10455 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010456 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000010457 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010458 }
10459 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010460 case XML_SCHEMA_FACET_MININCLUSIVE:
10461 case XML_SCHEMA_FACET_MINEXCLUSIVE:
10462 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010463 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
10464 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010465 /*
10466 * Okay we need to validate the value
10467 * at that point.
10468 */
10469 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010470 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010471
10472 /* 4.3.5.5 Constraints on enumeration Schema Components
10473 * Schema Component Constraint: enumeration valid restriction
10474 * It is an ·error· if any member of {value} is not in the
10475 * ·value space· of {base type definition}.
10476 *
10477 * minInclusive, maxInclusive, minExclusive, maxExclusive:
10478 * The value ·must· be in the
10479 * ·value space· of the ·base type·.
10480 */
10481 /*
10482 * This function is intended to deliver a compiled value
10483 * on the facet. In XML Schemas the type holding a facet,
10484 * cannot be a built-in type. Thus to ensure that other API
10485 * calls (relaxng) do work, if the given type is a built-in
10486 * type, we will assume that the given built-in type *is
10487 * already* the base type.
10488 */
10489 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
10490 base = typeDecl->baseType;
10491 if (base == NULL) {
10492 xmlSchemaPErr(ctxt, typeDecl->node,
10493 XML_SCHEMAS_ERR_INTERNAL,
10494 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010495 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010496 typeDecl->name, NULL);
10497 return (-1);
10498 }
10499 } else
10500 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010501 /*
10502 * TODO: Try to avoid creating a new context.
10503 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010504 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010505 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010506 xmlSchemaPErr(ctxt, typeDecl->node,
10507 XML_SCHEMAS_ERR_INTERNAL,
10508 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010509 "creating a new validation context.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010510 typeDecl->name, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010511 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010512 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010513 vctxt->type = base;
10514 ret = xmlSchemaValidateSimpleTypeValue(vctxt, facet->value, 0, 1, 1);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010515 facet->val = vctxt->value;
10516 vctxt->value = NULL;
10517 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010518 /* error code */
10519 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010520 xmlSchemaPErrExt(ctxt, facet->node,
10521 XML_SCHEMAP_INVALID_FACET,
10522 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010523 "Type definition '%s': The value '%s' of the "
10524 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010525 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010526 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000010527 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010528 }
10529 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010530 } else if (ret < 0) {
10531 xmlSchemaPErrExt(ctxt, facet->node,
10532 XML_SCHEMAS_ERR_INTERNAL,
10533 NULL, NULL, NULL,
10534 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010535 "failed to validate the value '%s' name of the "
10536 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000010537 facet->value,
10538 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
10539 base->name, NULL, NULL);
10540 ret = -1;
10541 }
10542 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010543 break;
10544 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 case XML_SCHEMA_FACET_PATTERN:
10546 facet->regexp = xmlRegexpCompile(facet->value);
10547 if (facet->regexp == NULL) {
10548 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010549 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010550 "Type definition '%s': The value '%s' of the "
10551 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010552 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010553 ret = -1;
10554 }
10555 break;
10556 case XML_SCHEMA_FACET_TOTALDIGITS:
10557 case XML_SCHEMA_FACET_FRACTIONDIGITS:
10558 case XML_SCHEMA_FACET_LENGTH:
10559 case XML_SCHEMA_FACET_MAXLENGTH:
10560 case XML_SCHEMA_FACET_MINLENGTH:{
10561 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010562
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010563 tmp =
10564 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
10565 facet->value,
10566 &facet->val);
10567 if (tmp != 0) {
10568 /* error code */
10569 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010570 xmlSchemaPErrExt(ctxt, facet->node,
10571 XML_SCHEMAP_INVALID_FACET_VALUE,
10572 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010573 "Type definition '%s': The value '%s' of the "
10574 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010575 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010576 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000010577 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010578 }
10579 ret = -1;
10580 }
10581 break;
10582 }
10583 case XML_SCHEMA_FACET_WHITESPACE:{
10584 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
10585 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
10586 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
10587 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
10588 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
10589 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
10590 } else {
10591 if (ctxt != NULL) {
10592 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010593 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 "Type definition '%s': The value '%s' of the "
10595 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010596 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010597 }
10598 ret = -1;
10599 }
10600 }
10601 default:
10602 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010603 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010604 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000010605}
10606
10607/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010608 * xmlSchemaCheckDefaults:
10609 * @typeDecl: the schema type definition
10610 * @ctxt: the schema parser context
10611 *
10612 * Checks the default values types, especially for facets
10613 */
10614static void
10615xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010616 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000010617{
Daniel Veillard4255d502002-04-16 15:50:10 +000010618 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010619 name = typeDecl->name;
10620 /*
10621 * NOTE: It is intended to use the facets list, instead
10622 * of facetSet.
10623 */
10624 if (typeDecl->facets != NULL) {
10625 xmlSchemaFacetPtr facet = typeDecl->facets;
10626
10627 while (facet != NULL) {
10628 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
10629 facet = facet->next;
10630 }
10631 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010632}
10633
10634/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000010635 * xmlSchemaAttrGrpFixup:
10636 * @attrgrpDecl: the schema attribute definition
10637 * @ctxt: the schema parser context
10638 * @name: the attribute name
10639 *
10640 * Fixes finish doing the computations on the attributes definitions
10641 */
10642static void
Daniel Veillard3646d642004-06-02 19:19:14 +000010643xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010644 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000010645{
10646 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000010647 name = attrgrp->name;
10648 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010649 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000010650 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010651 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000010652
Daniel Veillardc0826a72004-08-10 14:17:33 +000010653 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
10654 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010655 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010656 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010657 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010658 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
10659 "ref", attrgrp->ref, attrgrp->refNs,
10660 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010661 return;
10662 }
10663 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010664 attrgrp->attributes = ref->attributes;
10665 attrgrp->attributeWildcard = ref->attributeWildcard;
10666 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000010667}
10668
10669/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010670 * xmlSchemaAttrFixup:
10671 * @attrDecl: the schema attribute definition
10672 * @ctxt: the schema parser context
10673 * @name: the attribute name
10674 *
10675 * Fixes finish doing the computations on the attributes definitions
10676 */
10677static void
10678xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010679 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000010680{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010681 /*
10682 * TODO: If including this is done twice (!) for every attribute.
10683 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010684 /*
10685 * The simple type definition corresponding to the <simpleType> element
10686 * information item in the [children], if present, otherwise the simple
10687 * type definition ·resolved· to by the ·actual value· of the type
10688 * [attribute], if present, otherwise the ·simple ur-type definition·.
10689 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010690 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
10691 return;
10692 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010693 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010694 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010695 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010696 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010697 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010698 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010699
Daniel Veillard01fa6152004-06-29 17:04:39 +000010700 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
10701 attrDecl->typeNs);
10702 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010703 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010704 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010705 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
10706 "type", attrDecl->typeName, attrDecl->typeNs,
10707 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010708 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010709 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010710 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010711 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000010712
Daniel Veillardc0826a72004-08-10 14:17:33 +000010713 /*
10714 * TODO: Evaluate, what errors could occur if the declaration is not
10715 * found. It might be possible that the "typefixup" might crash if
10716 * no ref declaration was found.
10717 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010718 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010719 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010720 xmlSchemaPResCompAttrErr(ctxt,
10721 XML_SCHEMAP_SRC_RESOLVE,
10722 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
10723 "ref", attrDecl->ref, attrDecl->refNs,
10724 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010725 return;
10726 }
10727 xmlSchemaAttrFixup(ref, ctxt, NULL);
10728 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000010729 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010730 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000010731 }
10732}
10733
10734/**
10735 * xmlSchemaParse:
10736 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000010737 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000010738 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000010739 * XML Shema struture which can be used to validate instances.
10740 * *WARNING* this interface is highly subject to change
10741 *
10742 * Returns the internal XML Schema structure built from the resource or
10743 * NULL in case of error
10744 */
10745xmlSchemaPtr
10746xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
10747{
10748 xmlSchemaPtr ret = NULL;
10749 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010750 xmlNodePtr root;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010751 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010752 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010753
10754 xmlSchemaInitTypes();
10755
Daniel Veillard6045c902002-10-09 21:13:59 +000010756 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000010757 return (NULL);
10758
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010759 nberrors = ctxt->nberrors;
10760 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010761 ctxt->counter = 0;
10762 ctxt->container = NULL;
10763
10764 /*
10765 * First step is to parse the input document into an DOM/Infoset
10766 */
Daniel Veillard6045c902002-10-09 21:13:59 +000010767 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010768 doc = xmlReadFile((const char *) ctxt->URL, NULL,
10769 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770 if (doc == NULL) {
10771 xmlSchemaPErr(ctxt, NULL,
10772 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010773 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010774 ctxt->URL, NULL);
10775 return (NULL);
10776 }
Daniel Veillard6045c902002-10-09 21:13:59 +000010777 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010778 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
10779 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010780 if (doc == NULL) {
10781 xmlSchemaPErr(ctxt, NULL,
10782 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010783 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010784 NULL, NULL);
10785 return (NULL);
10786 }
10787 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000010788 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000010789 } else if (ctxt->doc != NULL) {
10790 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010791 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000010792 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010793 xmlSchemaPErr(ctxt, NULL,
10794 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010795 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010796 NULL, NULL);
10797 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010798 }
10799
10800 /*
10801 * Then extract the root and Schema parse it
10802 */
10803 root = xmlDocGetRootElement(doc);
10804 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010805 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10806 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010807 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000010808 if (!preserve) {
10809 xmlFreeDoc(doc);
10810 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010811 return (NULL);
10812 }
10813
10814 /*
10815 * Remove all the blank text nodes
10816 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010817 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000010818
10819 /*
10820 * Then do the parsing for good
10821 */
10822 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000010823 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000010824 if (!preserve) {
10825 xmlFreeDoc(doc);
10826 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010827 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000010828 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010829 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010830 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000010831 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010832 ctxt->ctxtType = NULL;
10833 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010834 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000010835 * Then fixup all attributes declarations
10836 */
10837 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
10838
10839 /*
10840 * Then fixup all attributes group declarations
10841 */
10842 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
10843 ctxt);
10844
10845 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000010846 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000010847 */
10848 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
10849
10850 /*
10851 * Then fix references of element declaration; apply constraints.
10852 */
10853 xmlHashScanFull(ret->elemDecl,
10854 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010855
10856 /*
10857 * Then build the content model for all elements
10858 */
10859 xmlHashScan(ret->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010860 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010861
10862 /*
10863 * Then check the defaults part of the type like facets values
10864 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010865 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
10866 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000010867
Daniel Veillardc0826a72004-08-10 14:17:33 +000010868
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010869 if (ctxt->nberrors != 0) {
10870 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010871 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010872 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010873 return (ret);
10874}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010875
Daniel Veillard4255d502002-04-16 15:50:10 +000010876/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000010877 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000010878 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000010879 * @err: the error callback
10880 * @warn: the warning callback
10881 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000010882 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000010883 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000010884 */
10885void
10886xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010887 xmlSchemaValidityErrorFunc err,
10888 xmlSchemaValidityWarningFunc warn, void *ctx)
10889{
Daniel Veillard4255d502002-04-16 15:50:10 +000010890 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010891 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010892 ctxt->error = err;
10893 ctxt->warning = warn;
10894 ctxt->userData = ctx;
10895}
10896
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010897/**
10898 * xmlSchemaFacetTypeToString:
10899 * @type: the facet type
10900 *
10901 * Convert the xmlSchemaTypeType to a char string.
10902 *
10903 * Returns the char string representation of the facet type if the
10904 * type is a facet and an "Internal Error" string otherwise.
10905 */
10906static const char *
10907xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
10908{
10909 switch (type) {
10910 case XML_SCHEMA_FACET_PATTERN:
10911 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010912 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010913 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010914 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010915 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010916 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010917 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010918 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010919 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010920 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010921 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010922 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010923 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010924 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010925 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010926 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010927 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010928 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010929 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010930 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010931 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010932 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000010933 return ("fractionDigits");
10934 default:
10935 break;
10936 }
10937 return ("Internal Error");
10938}
10939
Daniel Veillardc0826a72004-08-10 14:17:33 +000010940static xmlChar *
10941xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
10942 const xmlChar *cur = value;
10943 xmlChar *ret = NULL, *mcur;
10944
10945 if (value == NULL)
10946 return(NULL);
10947
10948 while ((*cur != 0) &&
10949 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
10950 cur++;
10951 }
10952 if (*cur == 0)
10953 return (NULL);
10954 ret = xmlStrdup(value);
10955 /* TODO FIXME: I guess gcc will bark at this. */
10956 mcur = (xmlChar *) (ret + (cur - value));
10957 do {
10958 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
10959 *mcur = ' ';
10960 mcur++;
10961 } while (*mcur != 0);
10962 return(ret);
10963}
10964
10965static int
10966xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
10967{
10968 xmlSchemaTypePtr anc;
10969
10970 /*
10971 * The normalization type can be changed only for types which are derived
10972 * from xsd:string.
10973 */
10974 if (type->type == XML_SCHEMA_TYPE_BASIC) {
10975 if ((type->builtInType == XML_SCHEMAS_STRING) &&
10976 (type->builtInType == XML_SCHEMAS_NORMSTRING))
10977
10978 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
10979 else {
10980 /*
10981 * For all ·atomic· datatypes other than string (and types ·derived·
10982 * by ·restriction· from it) the value of whiteSpace is fixed to
10983 * collapse
10984 */
10985 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
10986 }
10987 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10988 /*
10989 * For list types the facet "whiteSpace" is fixed to "collapse".
10990 */
10991 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
10992 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10993 return (-1);
10994 } else if (type->facetSet != NULL) {
10995 xmlSchemaTypePtr anyST;
10996 xmlSchemaFacetLinkPtr lin;
10997
10998 /*
10999 * Atomic types.
11000 */
11001 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11002 anc = type->baseType;
11003 do {
11004 /*
11005 * For all ·atomic· datatypes other than string (and types ·derived·
11006 * by ·restriction· from it) the value of whiteSpace is fixed to
11007 * collapse
11008 */
11009 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
11010 (anc->builtInType == XML_SCHEMAS_STRING)) {
11011
11012 lin = type->facetSet;
11013 do {
11014 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
11015 if (lin->facet->whitespace ==
11016 XML_SCHEMAS_FACET_COLLAPSE) {
11017 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11018 } else if (lin->facet->whitespace ==
11019 XML_SCHEMAS_FACET_REPLACE) {
11020 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
11021 } else
11022 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
11023 break;
11024 }
11025 lin = lin->next;
11026 } while (lin != NULL);
11027 break;
11028 }
11029 anc = anc->baseType;
11030 } while (anc != anyST);
11031 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
11032 }
11033 return (-1);
11034}
11035
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011036/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000011037 * xmlSchemaValidateFacetsInternal:
11038 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000011040 * @facets: the list of facets to check
11041 * @value: the lexical repr of the value to validate
11042 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000011043 * @fireErrors: if 0, only internal errors will be fired;
11044 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000011045 *
11046 * Check a value against all facet conditions
11047 *
11048 * Returns 0 if the element is schemas valid, a positive error code
11049 * number otherwise and -1 in case of internal or API error.
11050 */
11051static int
11052xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 xmlSchemaTypePtr type,
11054 const xmlChar * value,
11055 unsigned long length,
11056 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011057{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011058 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011059 xmlSchemaTypePtr biType; /* The build-in type. */
11060 xmlSchemaTypePtr tmpType;
11061 xmlSchemaFacetLinkPtr facetLink;
11062 int retFacet, hasFacet;
11063 xmlSchemaFacetPtr facet;
11064 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011065
Daniel Veillardc0826a72004-08-10 14:17:33 +000011066#ifdef DEBUG_UNION_VALIDATION
11067 printf("Facets of type: '%s'\n", (const char *) type->name);
11068 printf(" fireErrors: %d\n", fireErrors);
11069#endif
11070
11071 /*
11072 * NOTE: Do not jump away, if the facetSet of the given type is
11073 * empty: until now, "pattern" facets of the *base types* need to
11074 * be checked as well.
11075 */
11076 biType = type->baseType;
11077 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
11078 biType = biType->baseType;
11079 if (biType == NULL) {
11080 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11081 "Internal error: xmlSchemaValidateFacetsInternal, "
11082 "the base type axis of the given type '%s' does not resolve to "
11083 "a built-in type.\n",
11084 type->name, NULL);
11085 return (-1);
11086 }
11087
11088 if (type->facetSet != NULL) {
11089 facetLink = type->facetSet;
11090 while (facetLink != NULL) {
11091 facet = facetLink->facet;
11092 /*
11093 * Skip the pattern "whiteSpace": it is used to
11094 * format the character content beforehand.
11095 */
11096 switch (facet->type) {
11097 case XML_SCHEMA_FACET_WHITESPACE:
11098 case XML_SCHEMA_FACET_PATTERN:
11099 case XML_SCHEMA_FACET_ENUMERATION:
11100 break;
11101 case XML_SCHEMA_FACET_LENGTH:
11102 case XML_SCHEMA_FACET_MINLENGTH:
11103 case XML_SCHEMA_FACET_MAXLENGTH:
11104 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11105 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
11106 value, length, 0);
11107 len = length;
11108 } else
11109 ret = xmlSchemaValidateLengthFacet(biType, facet,
11110 value, ctxt->value, &len);
11111 break;
11112 default:
11113 ret = xmlSchemaValidateFacet(biType, facet, value,
11114 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011115 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 if (ret < 0) {
11117 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11118 "Internal error: xmlSchemaValidateFacetsInternal, "
11119 "validating facet of type '%s'.\n",
11120 type->name, NULL);
11121 break;
11122 } else if ((ret > 0) && (fireErrors)) {
11123 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, len,
11124 type, facet, NULL, NULL, NULL, NULL);
11125 }
11126
11127 facetLink = facetLink->next;
11128 }
11129 if (ret >= 0) {
11130 /*
11131 * Process enumerations.
11132 */
11133 retFacet = 0;
11134 facetLink = type->facetSet;
11135 while (facetLink != NULL) {
11136 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
11137 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
11138 value, ctxt->value);
11139 if (retFacet <= 0)
11140 break;
11141 }
11142 facetLink = facetLink->next;
11143 }
11144 if (retFacet > 0) {
11145 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
11146 if (fireErrors)
11147 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur,
11148 value, 0, type, NULL, NULL, NULL, NULL, NULL);
11149 } else if (retFacet < 0) {
11150 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11151 "Internal error: xmlSchemaValidateFacetsInternal, "
11152 "validating facet of type '%s'.\n",
11153 BAD_CAST "enumeration", NULL);
11154 ret = -1;
11155 }
11156 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011157 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011158 if (ret >= 0) {
11159 /*
11160 * Process patters. Pattern facets are ORed at type level
11161 * and ANDed if derived. Walk the base type axis.
11162 */
11163 hasFacet = 0;
11164 tmpType = type;
11165 facet = NULL;
11166 do {
11167 retFacet = 0;
11168 for (facetLink = tmpType->facetSet; facetLink != NULL;
11169 facetLink = facetLink->next) {
11170 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
11171 continue;
11172 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
11173 value, ctxt->value);
11174 if (retFacet <= 0)
11175 break;
11176 else
11177 /* Save the last non-validating facet. */
11178 facet = facetLink->facet;
11179 }
11180 if (retFacet != 0)
11181 break;
11182 tmpType = tmpType->baseType;
11183 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
11184 if (retFacet < 0) {
11185 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11186 "Internal error: xmlSchemaValidateSimpleTypeValue, "
11187 "validating 'pattern' facets of type '%s'.\n",
11188 tmpType->name, NULL);
11189 ret = -1;
11190 } else if (retFacet > 0) {
11191 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
11192 if (fireErrors) {
11193 xmlSchemaVFacetErr(ctxt, ret, ctxt->cur, value, 0, type, facet,
11194 NULL, NULL, NULL, NULL);
11195 }
11196 }
11197 }
11198
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000011199 return (ret);
11200}
11201
Daniel Veillard4255d502002-04-16 15:50:10 +000011202/************************************************************************
11203 * *
11204 * Simple type validation *
11205 * *
11206 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000011207
Daniel Veillard4255d502002-04-16 15:50:10 +000011208
11209/************************************************************************
11210 * *
11211 * DOM Validation code *
11212 * *
11213 ************************************************************************/
11214
11215static int xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +000011217static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011218 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000011219 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000011220static int xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011221 xmlNodePtr elem,
11222 xmlSchemaElementPtr elemDecl,
11223 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000011224
Daniel Veillard3646d642004-06-02 19:19:14 +000011225
11226/**
11227 * xmlSchemaFreeAttrStates:
11228 * @state: a list of attribute states
11229 *
11230 * Free the given list of attribute states
11231 *
11232 */
11233static void
11234xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
11235{
11236 xmlSchemaAttrStatePtr tmp;
11237 while (state != NULL) {
11238 tmp = state;
11239 state = state->next;
11240 xmlFree(tmp);
11241 }
11242}
11243
Daniel Veillard4255d502002-04-16 15:50:10 +000011244/**
11245 * xmlSchemaRegisterAttributes:
11246 * @ctxt: a schema validation context
11247 * @attrs: a list of attributes
11248 *
11249 * Register the list of attributes as the set to be validated on that element
11250 *
11251 * Returns -1 in case of error, 0 otherwise
11252 */
11253static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011254xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
11255{
Daniel Veillard3646d642004-06-02 19:19:14 +000011256 xmlSchemaAttrStatePtr tmp;
11257
11258 ctxt->attr = NULL;
11259 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011260 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011261 if ((attrs->ns != NULL) &&
11262 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
11263 attrs = attrs->next;
11264 continue;
11265 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011266 tmp = (xmlSchemaAttrStatePtr)
11267 xmlMalloc(sizeof(xmlSchemaAttrState));
11268 if (tmp == NULL) {
11269 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
11270 return (-1);
11271 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011272 tmp->attr = attrs;
11273 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
11274 tmp->next = NULL;
11275 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011277 else
11278 ctxt->attrTop->next = tmp;
11279 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011280 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011281 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011282 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011283}
11284
11285/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011286 * xmlSchemaValidateCheckNodeList
11287 * @nodelist: the list of nodes
11288 *
11289 * Check the node list is only made of text nodes and entities pointing
11290 * to text nodes
11291 *
11292 * Returns 1 if true, 0 if false and -1 in case of error
11293 */
11294static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
11296{
Daniel Veillard4255d502002-04-16 15:50:10 +000011297 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 if (nodelist->type == XML_ENTITY_REF_NODE) {
11299 TODO /* implement recursion in the entity content */
11300 }
11301 if ((nodelist->type != XML_TEXT_NODE) &&
11302 (nodelist->type != XML_COMMENT_NODE) &&
11303 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000011304 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011305 return (0);
11306 }
11307 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011308 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011310}
11311
11312/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011313 * xmlSchemaValidateCallback:
11314 * @ctxt: a schema validation context
11315 * @name: the name of the element detected (might be NULL)
11316 * @type: the type
11317 *
11318 * A transition has been made in the automata associated to an element
11319 * content model
11320 */
11321static void
11322xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011323 const xmlChar * name ATTRIBUTE_UNUSED,
11324 xmlSchemaTypePtr type, xmlNodePtr node)
11325{
Daniel Veillard4255d502002-04-16 15:50:10 +000011326 xmlSchemaTypePtr oldtype = ctxt->type;
11327 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011328
Daniel Veillard4255d502002-04-16 15:50:10 +000011329#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000011330 xmlGenericError(xmlGenericErrorContext,
11331 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011332 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011333#endif
11334 ctxt->type = type;
11335 ctxt->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011336 xmlSchemaValidateContent(ctxt, node);
Daniel Veillard4255d502002-04-16 15:50:10 +000011337 ctxt->type = oldtype;
11338 ctxt->node = oldnode;
11339}
11340
Daniel Veillard01fa6152004-06-29 17:04:39 +000011341#if 0 /* Not used any more */
Daniel Veillard4255d502002-04-16 15:50:10 +000011342/**
11343 * xmlSchemaValidateSimpleType:
11344 * @ctxt: a schema validation context
11345 * @node: the top node.
11346 *
11347 * Validate the content of an simple type.
11348 *
11349 * Returns 0 if the element is schemas valid, a positive error code
11350 * number otherwise and -1 in case of internal or API error.
11351 */
11352static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011353xmlSchemaValidateSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
11354{
Daniel Veillard4255d502002-04-16 15:50:10 +000011355 xmlNodePtr child;
William M. Bracke7091952004-05-11 15:09:58 +000011356 xmlSchemaTypePtr type, base, variety;
Daniel Veillard4255d502002-04-16 15:50:10 +000011357 xmlAttrPtr attr;
11358 int ret;
William M. Bracke7091952004-05-11 15:09:58 +000011359 xmlChar *value;
11360
Daniel Veillard4255d502002-04-16 15:50:10 +000011361
11362 child = ctxt->node;
11363 type = ctxt->type;
11364
11365 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000011366 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11367 "Internal error: xmlSchemaValidateSimpleType %s\n",
11368 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011369 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011370 }
11371 /*
11372 * Only text and text based entities references shall be found there
11373 */
11374 ret = xmlSchemaValidateCheckNodeList(child);
11375 if (ret < 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011376 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11377 "Internal error: xmlSchemaValidateSimpleType %s content\n",
11378 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011379 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011380 } else if (ret == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011381 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_NOTSIMPLE,
11382 "Element %s content is not a simple type\n",
11383 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011384 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011385 }
11386 /*
11387 * Validation Rule: Element Locally Valid (Type): 3.1.1
William M. Bracke7091952004-05-11 15:09:58 +000011388 */
11389
Daniel Veillard4255d502002-04-16 15:50:10 +000011390 attr = node->properties;
11391 while (attr != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392 if ((attr->ns == NULL) ||
11393 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
11394 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
11395 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
11396 (!xmlStrEqual(attr->name, BAD_CAST "schemasLocation")) &&
11397 (!xmlStrEqual
11398 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
William M. Bracke7091952004-05-11 15:09:58 +000011399 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDATTR,
11400 "Element %s: attribute %s should not be present\n",
11401 node->name, attr->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011402 return (ctxt->err);
11403 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011404 }
William M. Bracke7091952004-05-11 15:09:58 +000011405 /* TODO:
11406 * If {variety} is ·atomic· then the {variety} of {base type definition}
11407 * must be ·atomic·.
11408 * If {variety} is ·list· then the {variety} of {item type definition}
11409 * must be either ·atomic· or ·union·.
11410 * If {variety} is ·union· then {member type definitions} must be a list
11411 * of datatype definitions.
11412 */
11413 if (type->subtypes == NULL) {
11414 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11415 "Internal error: xmlSchemaValidateSimpleType; "
11416 "simple type %s does not define a variety\n",
11417 node->name, NULL);
11418 return (ctxt->err);
11419 }
11420 /* Varieties: Restriction or List or Union. */
11421 variety = type->subtypes;
11422 ctxt->type = variety;
11423 value = xmlNodeGetContent(child);
11424 switch (variety->type) {
11425 case XML_SCHEMA_TYPE_RESTRICTION:{
William M. Bracke7091952004-05-11 15:09:58 +000011426 base = variety->baseType;
11427 if (base != NULL) {
11428 ret = xmlSchemaValidateSimpleValue(ctxt, base, value);
11429 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011430 TODO}
William M. Bracke7091952004-05-11 15:09:58 +000011431 break;
11432 }
11433 case XML_SCHEMA_TYPE_LIST:
11434 case XML_SCHEMA_TYPE_UNION: {
11435 ret = xmlSchemaValidateSimpleValue(ctxt, variety, value);
11436 break;
11437 }
11438 default:{
11439 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11440 "Internal error: xmlSchemaValidateSimpleType; "
11441 "simple type %s defines unknown content: %s\n",
11442 variety->name, NULL);
11443 ret = ctxt->err;
11444 }
11445 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011446 if ((ret == 0) && (variety->facetSet != NULL)) {
11447 ret = xmlSchemaValidateFacets(ctxt, base, variety->facetSet, value);
11448 }
William M. Bracke7091952004-05-11 15:09:58 +000011449 if (value != NULL)
11450 xmlFree(value);
11451
11452 /* This was removed, since a simple content is not a content of a
11453 * simple type, but of a complex type.
11454 * ret = xmlSchemaValidateSimpleContent(ctxt, node);
11455 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011456 ctxt->type = type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011457 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000011458}
Daniel Veillard01fa6152004-06-29 17:04:39 +000011459#endif
11460
Daniel Veillardc0826a72004-08-10 14:17:33 +000011461
11462
Daniel Veillard01fa6152004-06-29 17:04:39 +000011463/**
11464 * xmlSchemaValidateSimpleTypeValue:
11465 * @ctxt: a schema validation context
11466 * @value: the value to be validated
11467 * @fireErrors: shall errors be reported?
11468 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000011469 * @normalize: shall the value be normalized?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011470 *
11471 * Validates a value by the given type (user derived or built-in).
11472 *
11473 * Returns 0 if the value is valid, a positive error code
11474 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011475 */
11476static int
11477xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
11478 const xmlChar *value,
11479 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011480 int applyFacets,
11481 int normalize)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011482{
11483 xmlSchemaTypePtr type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011484 int ret = 0;
11485 xmlChar *normValue = NULL;
11486 int wtsp;
11487
11488 type = ctxt->type;
11489 wtsp = ctxt->valueWS;
11490 /*
11491 * Normalize the value.
11492 */
11493 if (normalize &&
11494 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
11495 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
11496
11497 if ((norm != -1) && (norm > ctxt->valueWS)) {
11498 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
11499 normValue = xmlSchemaCollapseString(value);
11500 else
11501 normValue = xmlSchemaWhiteSpaceReplace(value);
11502 ctxt->valueWS = norm;
11503 if (normValue != NULL)
11504 value = (const xmlChar *) normValue;
11505 }
11506 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011507 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11508 xmlNodePtr child;
11509
11510 if (ctxt->value != NULL) {
11511 xmlSchemaFreeValue(ctxt->value);
11512 ctxt->value = NULL;
11513 }
11514 child = ctxt->node;
11515 while (child != NULL) {
11516 switch (child->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011517 case XML_TEXT_NODE:
11518 case XML_CDATA_SECTION_NODE:
11519 case XML_PI_NODE:
11520 case XML_COMMENT_NODE:
11521 case XML_XINCLUDE_START:
11522 case XML_XINCLUDE_END:
11523 break;
11524 case XML_ENTITY_REF_NODE:
11525 case XML_ENTITY_NODE:
11526 TODO break;
11527 case XML_ELEMENT_NODE: {
11528 xmlChar *strE = NULL;
11529
11530 xmlSchemaVErrExt(ctxt, ctxt->cur,
11531 XML_SCHEMAS_ERR_INVALIDELEM,
11532 "Element '%s': The child '%s' should "
11533 "not be present.\n",
11534 xmlSchemaFormatNsPrefixLocal(&strE,
11535 ctxt->cur->parent->ns, ctxt->cur->parent->name),
11536 child->name, NULL, NULL, NULL);
11537 FREE_AND_NULL(strE);
11538 return (ctxt->err);
11539 }
11540 case XML_ATTRIBUTE_NODE:
11541 case XML_DOCUMENT_NODE:
11542 case XML_DOCUMENT_TYPE_NODE:
11543 case XML_DOCUMENT_FRAG_NODE:
11544 case XML_NOTATION_NODE:
11545 case XML_HTML_DOCUMENT_NODE:
11546 case XML_DTD_NODE:
11547 case XML_ELEMENT_DECL:
11548 case XML_ATTRIBUTE_DECL:
11549 case XML_ENTITY_DECL:
11550 case XML_NAMESPACE_DECL:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011551#ifdef LIBXML_DOCB_ENABLED
Daniel Veillardc0826a72004-08-10 14:17:33 +000011552 case XML_DOCB_DOCUMENT_NODE:
11553#endif
11554 {
11555 xmlChar *strE = NULL, *strA = NULL;
11556
11557 if (ctxt->cur->type == XML_ATTRIBUTE_NODE) {
11558 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
11559 "Element '%s', attribute '%s': The type of node is "
11560 "unexpected here.\n",
11561 xmlSchemaFormatNsPrefixLocal(&strE, ctxt->cur->parent->ns,
11562 ctxt->cur->parent->name),
11563 xmlSchemaFormatNsPrefixLocal(&strA, ctxt->cur->ns,
11564 ctxt->cur->name));
11565 } else {
11566 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INVALIDELEM,
11567 "Element '%s': The type of node is unexpected here.\n",
11568 xmlSchemaFormatNsPrefixLocal(&strE, ctxt->cur->ns,
11569 ctxt->cur->name), NULL);
11570 }
11571 FREE_AND_NULL(strE);
11572 FREE_AND_NULL(strA);
11573 return (ctxt->err);
11574 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011575 }
11576 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011577
11578 }
11579 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), ctxt->cur);
11580 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011581 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
11582 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
11583 else
11584 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011585 if (fireErrors)
11586 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011587 } else if (ret < 0) {
11588 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11589 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011590 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011591 }
11592 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11593 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
11594 * a literal in the ·lexical space· of {base type definition}
11595 */
11596 ctxt->type = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011597 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 0, 0);
11598 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011599 if (ret < 0) {
11600 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11601 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011602 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011603 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011604 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011605 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011606 if (fireErrors)
11607 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
11608 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011609 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011610 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011611 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011612 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
11613 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011614 if (ret < 0) {
11615 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11616 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011617 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011618 type->name, NULL);
11619 } else if (ret > 0) {
11620 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011621 /*
11622 Disabled, since the facet validation already reports errors.
11623 if (fireErrors)
11624 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
11625 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011626 }
11627 }
11628 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11629
11630 xmlSchemaTypePtr tmpType;
11631 const xmlChar *cur, *end;
11632 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011633 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011634
11635 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
11636 * of white space separated tokens, each of which ·match·es a literal
11637 * in the ·lexical space· of {item type definition}
11638 */
11639
Daniel Veillardc0826a72004-08-10 14:17:33 +000011640 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011641 cur = value;
11642 do {
11643 while (IS_BLANK_CH(*cur))
11644 cur++;
11645 end = cur;
11646 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
11647 end++;
11648 if (end == cur)
11649 break;
11650 tmp = xmlStrndup(cur, end - cur);
11651 len++;
11652 ctxt->type = tmpType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011653 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmp, 0, 1, 0);
11654 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011655 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011656 if (ret < 0) {
11657 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11658 "Internal error: xmlSchemaValidateSimpleTypeValue, "
11659 "validating an item of list simple type '%s'\n",
11660 type->name, NULL);
11661 break;
11662 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011663 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011664 if (fireErrors)
11665 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011666 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011667 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011668 cur = end;
11669 } while (*cur != 0);
11670 /*
11671 * Check facets.
11672 */
11673 if (ret < 0) {
11674 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11675 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011676 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011677 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011678 } else if ((ret == 0) && (applyFacets)) {
11679 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
11680 value, len, fireErrors);
11681 if (ret < 0) {
11682 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11683 "Internal error: xmlSchemaValidateSimpleTypeValue, "
11684 "validating facets of list simple type '%s'\n",
11685 type->name, NULL);
11686 } else if (ret > 0) {
11687 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011688 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011689 Disabled, since the facet validation already reports errors.
11690 if (fireErrors)
11691 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011692 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011693 }
11694
Daniel Veillard01fa6152004-06-29 17:04:39 +000011695 }
11696 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11697 xmlSchemaTypeLinkPtr memberLink;
11698
11699 /*
11700 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
11701 * not apply directly; however, the normalization behavior of ·union·
11702 * types is controlled by the value of whiteSpace on that one of the
11703 * ·memberTypes· against which the ·union· is successfully validated.
11704 *
11705 * This means that the value is normalized by the first validating
11706 * member type, then the facets of the union type are applied. This
11707 * needs changing of the value!
11708 */
11709
11710 /*
11711 * 1.2.3 if {variety} is ·union· then the string must ·match· a
11712 * literal in the ·lexical space· of at least one member of
11713 * {member type definitions}
11714 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011715#ifdef DEBUG_UNION_VALIDATION
11716 printf("Union ST : '%s'\n", (const char *) type->name);
11717 printf(" fireErrors : %d\n", fireErrors);
11718 printf(" applyFacets: %d\n", applyFacets);
11719#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000011720 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
11721 if (memberLink == NULL) {
11722 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11723 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011724 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011725 type->name, NULL);
11726 ret = -1;
11727 }
11728 if (ret == 0) {
11729 while (memberLink != NULL) {
11730 ctxt->type = memberLink->type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011731 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 0, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011732 if ((ret <= 0) || (ret == 0))
11733 break;
11734 memberLink = memberLink->next;
11735 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011736 ctxt->type = type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011737 if (ret < 0) {
11738 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11739 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011740 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011741 type->name, NULL);
11742 } else if (ret > 0) {
11743 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011744 if (fireErrors)
11745 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
11746 }
11747 }
11748 /*
11749 * Apply facets (pattern, enumeration).
11750 */
11751 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
11752 int mws;
11753 /*
11754 * The normalization behavior of ·union· types is controlled by
11755 * the value of whiteSpace on that one of the ·memberTypes·
11756 * against which the ·union· is successfully validated.
11757 */
11758 if (normValue != NULL) {
11759 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11760 "Internal error: xmlSchemaValidateSimpleTypeValue, "
11761 "the value was already normalized for the union simple "
11762 "type '%s'.\n", type->name, NULL);
11763 }
11764 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
11765 if (mws > ctxt->valueWS) {
11766 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
11767 normValue = xmlSchemaCollapseString(value);
11768 else
11769 normValue = xmlSchemaWhiteSpaceReplace(value);
11770 if (normValue != NULL)
11771 value = (const xmlChar *) normValue;
11772 }
11773
11774 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
11775 value, 0, fireErrors);
11776 if (ret < 0) {
11777 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
11778 "Internal error: xmlSchemaValidateSimpleTypeValue, "
11779 "validating facets of union simple type '%s'\n",
11780 type->name, NULL);
11781 } else if (ret > 0) {
11782 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
11783 /*
11784 if (fireErrors)
11785 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
11786 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011787 }
11788 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011789 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011790 ctxt->type = type;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011791 ctxt->valueWS = wtsp;
11792 if (normValue != NULL)
11793 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011794 return (ret);
11795}
11796
11797/**
11798 * xmlSchemaValidateSimpleTypeElement:
11799 * @ctxt: a schema validation context
11800 * @node: the element node to be validated.
11801 *
11802 * Validate the element against a simple type.
11803 *
11804 * Returns 0 if the element is valid, a positive error code
11805 * number otherwise and -1 in case of an internal or API error.
11806 */
11807static int
11808xmlSchemaValidateSimpleTypeElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
11809{
11810 xmlNodePtr child;
11811 xmlSchemaTypePtr type;
11812 xmlAttrPtr attr;
11813 int ret;
11814 xmlChar *value;
11815
11816
11817 child = ctxt->node;
11818 type = ctxt->type;
11819
11820 if ((ctxt == NULL) || (type == NULL)) {
11821 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11822 "Internal error: xmlSchemaValidateSimpleTypeElement %s\n",
11823 node->name, NULL);
11824 return (-1);
11825 }
11826
11827 /*
11828 * Only text and text based entities references shall be found there
11829 */
11830 ret = xmlSchemaValidateCheckNodeList(child);
11831 if (ret < 0) {
11832 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11833 "Internal error: xmlSchemaValidateSimpleTypeElement %s content\n",
11834 node->name, NULL);
11835 return (-1);
11836 } else if (ret == 0) {
11837 /* 3.1.2 The element information item must have no element
11838 * information item [children].
11839 */
11840 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_TYPE_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011841 "Element '%s' must have no element children.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011842 node->name, NULL);
11843 return (-1);
11844 }
11845 /*
11846 * Validation Rule: Element Locally Valid (Type): 3.1.1
11847 */
11848 attr = node->properties;
11849 while (attr != NULL) {
11850 if ((attr->ns == NULL) ||
11851 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
11852 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
11853 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
11854 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
11855 (!xmlStrEqual
11856 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
11857 xmlSchemaVErr(ctxt, node,
11858 XML_SCHEMAV_CVC_TYPE_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011859 "The attributes of element '%s' must be empty, excepting "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011860 "those whose namespace name is identical to "
11861 "http://www.w3.org/2001/XMLSchema-instance and whose local "
11862 "name is one of type, nil, schemaLocation or "
11863 "noNamespaceSchemaLocation.\n",
11864 node->name, attr->name);
11865 return (ctxt->err);
11866 }
11867 attr = attr->next;
11868 }
11869 value = xmlNodeGetContent(child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011870 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011871 if (value != NULL)
11872 xmlFree(value);
11873
11874 ctxt->type = type;
11875 return (ret);
11876}
Daniel Veillard4255d502002-04-16 15:50:10 +000011877
11878/**
11879 * xmlSchemaValidateElementType:
11880 * @ctxt: a schema validation context
11881 * @node: the top node.
11882 *
11883 * Validate the content of an element type.
11884 * Validation Rule: Element Locally Valid (Complex Type)
11885 *
11886 * Returns 0 if the element is schemas valid, a positive error code
11887 * number otherwise and -1 in case of internal or API error.
11888 */
11889static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011890xmlSchemaValidateElementType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
11891{
Daniel Veillard4255d502002-04-16 15:50:10 +000011892 xmlNodePtr child;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011893 xmlRegExecCtxtPtr oldregexp; /* cont model of the parent */
Daniel Veillard4255d502002-04-16 15:50:10 +000011894 xmlSchemaElementPtr decl;
Daniel Veillard3646d642004-06-02 19:19:14 +000011895 int ret;
11896 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
11897
Daniel Veillard01fa6152004-06-29 17:04:39 +000011898 /* This one is called by xmlSchemaValidateContent only. */
Daniel Veillard3646d642004-06-02 19:19:14 +000011899 /*
11900 * TODO: Look into "xmlSchemaValidateElement" for missing parts, which should
11901 * go in here as well.
11902 */
11903
11904 /* TODO: Is this one called always with an element declaration as the
11905 * context's type?
11906 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011907
11908 oldregexp = ctxt->regexp;
11909
11910 child = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011911 decl = (xmlSchemaElementPtr) ctxt->type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011912
Daniel Veillardc0826a72004-08-10 14:17:33 +000011913 if ((ctxt == NULL) || (decl == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000011914 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
11915 "Internal error: xmlSchemaValidateElementType\n",
11916 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011917 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011918 }
11919 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011920 if (decl->minOccurs > 0) {
William M. Bracke7091952004-05-11 15:09:58 +000011921 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_MISSING,
11922 "Element %s: missing child %s\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +000011923 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011924 }
11925 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011926 }
11927
11928 /*
11929 * Verify the element matches
11930 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011931 if (!xmlStrEqual(child->name, decl->name)) {
William M. Bracke7091952004-05-11 15:09:58 +000011932 xmlSchemaVErr3(ctxt, node, XML_SCHEMAS_ERR_WRONGELEM,
11933 "Element %s: missing child %s found %s\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +000011934 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011935 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011936 }
11937 /*
11938 * Verify the attributes
11939 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011940 /*
11941 * TODO: This "attrTop" thing is not needed any more.
11942 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011943 attrs = ctxt->attr;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011944 attrTop = ctxt->attrTop;
11945 xmlSchemaRegisterAttributes(ctxt, child->properties);
11946 xmlSchemaValidateAttributes(ctxt, child, decl->subtypes);
11947 if (ctxt->attr != NULL)
11948 xmlSchemaFreeAttributeStates(ctxt->attr);
11949 ctxt->attr = attrs;
11950 ctxt->attrTop = attrTop;
Daniel Veillard3646d642004-06-02 19:19:14 +000011951
Daniel Veillard4255d502002-04-16 15:50:10 +000011952 /*
11953 * Verify the element content recursively
Daniel Veillardc0826a72004-08-10 14:17:33 +000011954 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011955 oldregexp = ctxt->regexp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011956 /*
11957 * FIXME TODO: This one creates a regexp even if no content
11958 * model was defined. Somehow ->contModel is always not NULL
11959 * for complex types, even if they are empty.
11960 */
11961 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011962 ctxt->regexp = xmlRegNewExecCtxt(decl->contModel,
11963 (xmlRegExecCallbacks)
11964 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000011965#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011966 xmlGenericError(xmlGenericErrorContext, "====> %s\n", node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011967#endif
11968 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011969 xmlSchemaValidateType(ctxt, child, decl, decl->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000011970
11971 if (decl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011972 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011973#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011974 xmlGenericError(xmlGenericErrorContext,
11975 "====> %s : %d\n", node->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000011976#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011977 if (ret == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011978 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
11979 node, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011980 } else if (ret < 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011981 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
11982 node, "The element content is not valid", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011983#ifdef DEBUG_CONTENT
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011984 } else {
11985 xmlGenericError(xmlGenericErrorContext,
11986 "Element %s content check succeeded\n",
11987 node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011988
11989#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011990 }
11991 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000011992 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011993 ctxt->regexp = oldregexp;
Daniel Veillard4255d502002-04-16 15:50:10 +000011994 ctxt->node = child;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011995 ctxt->type = (xmlSchemaTypePtr) decl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011996 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000011997}
11998
Daniel Veillard01fa6152004-06-29 17:04:39 +000011999#if 0 /* Not currently used. */
Daniel Veillard4255d502002-04-16 15:50:10 +000012000/**
12001 * xmlSchemaValidateBasicType:
12002 * @ctxt: a schema validation context
12003 * @node: the top node.
12004 *
12005 * Validate the content of an element expected to be a basic type type
12006 *
12007 * Returns 0 if the element is schemas valid, a positive error code
12008 * number otherwise and -1 in case of internal or API error.
12009 */
12010static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012011xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12012{
Daniel Veillard4255d502002-04-16 15:50:10 +000012013 int ret;
12014 xmlNodePtr child, cur;
12015 xmlSchemaTypePtr type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012016 xmlChar *value; /* lexical representation */
Daniel Veillard4255d502002-04-16 15:50:10 +000012017
12018 child = ctxt->node;
12019 type = ctxt->type;
12020
12021 if ((ctxt == NULL) || (type == NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000012022 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12023 "Internal error: xmlSchemaValidateBasicType\n",
12024 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012025 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000012026 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012027 if (type->type != XML_SCHEMA_TYPE_BASIC) {
12028 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12029 "Internal error: xmlSchemaValidateBasicType, "
12030 "the given type is not a built-in type.\n",
12031 node->name, NULL);
12032 return (-1);
12033 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012034 /*
12035 * First check the content model of the node.
12036 */
12037 cur = child;
12038 while (cur != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012039 switch (cur->type) {
12040 case XML_TEXT_NODE:
12041 case XML_CDATA_SECTION_NODE:
12042 case XML_PI_NODE:
12043 case XML_COMMENT_NODE:
12044 case XML_XINCLUDE_START:
12045 case XML_XINCLUDE_END:
12046 break;
12047 case XML_ENTITY_REF_NODE:
12048 case XML_ENTITY_NODE:
12049 TODO break;
12050 case XML_ELEMENT_NODE:
William M. Bracke7091952004-05-11 15:09:58 +000012051 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
12052 "Element %s: child %s should not be present\n",
12053 node->name, cur->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012054 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012055 case XML_ATTRIBUTE_NODE:
12056 case XML_DOCUMENT_NODE:
12057 case XML_DOCUMENT_TYPE_NODE:
12058 case XML_DOCUMENT_FRAG_NODE:
12059 case XML_NOTATION_NODE:
12060 case XML_HTML_DOCUMENT_NODE:
12061 case XML_DTD_NODE:
12062 case XML_ELEMENT_DECL:
12063 case XML_ATTRIBUTE_DECL:
12064 case XML_ENTITY_DECL:
12065 case XML_NAMESPACE_DECL:
12066#ifdef LIBXML_DOCB_ENABLED
12067 case XML_DOCB_DOCUMENT_NODE:
12068#endif
William M. Bracke7091952004-05-11 15:09:58 +000012069 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INVALIDELEM,
12070 "Element %s: node type of node unexpected here\n",
12071 node->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012072 return (ctxt->err);
12073 }
12074 cur = cur->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012075 }
12076 if (child == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012077 value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012078 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012079 value = xmlNodeGetContent(child->parent);
Daniel Veillard4255d502002-04-16 15:50:10 +000012080
12081 if (ctxt->value != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012082 xmlSchemaFreeValue(ctxt->value);
12083 ctxt->value = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012084 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012085
Daniel Veillard4255d502002-04-16 15:50:10 +000012086 ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
Daniel Veillard01fa6152004-06-29 17:04:39 +000012087
Daniel Veillard4255d502002-04-16 15:50:10 +000012088 if (value != NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012089 xmlFree(value);
Daniel Veillard4255d502002-04-16 15:50:10 +000012090 if (ret != 0) {
William M. Bracke7091952004-05-11 15:09:58 +000012091 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_VALUE,
12092 "Element %s: failed to validate basic type %s\n",
12093 node->name, type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012094 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012095 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000012096}
Daniel Veillard01fa6152004-06-29 17:04:39 +000012097#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012098
12099/**
Daniel Veillardc0826a72004-08-10 14:17:33 +000012100 * xmlSchemaValidateAnyInternal:
12101 * @ctxt: a schema validation context
12102 * @node: the top node.
12103 *
12104 * Represents the recursive portion of xmlSchemaValidateAny. Not
12105 * intended to be used by other functions.
12106 *
12107 * Returns 0 if the element is valid, a positive error code
12108 * number otherwise and -1 in case of an internal error.
12109 */
12110static int
12111xmlSchemaValidateAnyInternal(xmlSchemaValidCtxtPtr ctxt,
12112 xmlSchemaWildcardPtr wild,
12113 xmlNodePtr node)
12114{
12115 const xmlChar *uri;
12116 int ret = 0;
12117 xmlNodePtr child;
12118
12119 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
12120 xmlSchemaElementPtr decl = NULL;
12121
12122 if (node->ns != NULL)
12123 decl = xmlHashLookup3(ctxt->schema->elemDecl,
12124 node->name, node->ns->href, NULL);
12125 else
12126 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
12127 if (decl != NULL) {
12128 ctxt->node = node;
12129 ctxt->type = (xmlSchemaTypePtr) decl;
12130 ret = xmlSchemaValidateElementType(ctxt, node->parent);
12131 if (ret < 0) {
12132 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12133 "Internal error: xmlSchemaValidateAnyInternal, "
12134 "validating an element in the context of a wildcard.",
12135 NULL, NULL);
12136 } else if (ret > 0)
12137 return (ret);
12138 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
12139 /* TODO: Change to proper error code. */
12140 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAS_ERR_UNDECLAREDELEM,
12141 node, wild, "No matching element declaration found.");
12142 return (ctxt->err);
12143 }
12144 }
12145 if (node->children != NULL) {
12146 child = node->children;
12147 do {
12148 if (child->type == XML_ELEMENT_NODE) {
12149 if (child->ns != NULL)
12150 uri = child->ns->href;
12151 else
12152 uri = NULL;
12153 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
12154 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
12155 child, wild,
12156 "The namespace of the element is not allowed.");
12157 return (ctxt->err);
12158 }
12159 ret = xmlSchemaValidateAnyInternal(ctxt, wild, child);
12160 if (ret != 0)
12161 return (ret);
12162 }
12163 child = child->next;
12164 } while (child != NULL);
12165 }
12166 return (0);
12167}
12168
12169/**
12170 * xmlSchemaValidateAny:
12171 * @ctxt: a schema validation context
12172 *
12173 * Returns 0 if the element is valid, a positive error code
12174 * number otherwise and -1 in case of an internal or API error.
12175 */
12176static int
12177xmlSchemaValidateAny(xmlSchemaValidCtxtPtr ctxt)
12178{
12179 return(xmlSchemaValidateAnyInternal(ctxt,
12180 ctxt->type->attributeWildcard, ctxt->cur));
12181}
12182
12183/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012184 * xmlSchemaValidateComplexType:
12185 * @ctxt: a schema validation context
12186 * @node: the top node.
12187 *
12188 * Validate the content of an element expected to be a complex type type
12189 * xmlschema-1.html#cvc-complex-type
12190 * Validation Rule: Element Locally Valid (Complex Type)
12191 *
12192 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 * number otherwise and -1 in case of internal or API error.
12194 * Note on reported errors: Although it might be nice to report
12195 * the name of the simple/complex type, used to validate the content
12196 * of a node, it is quite unnecessary: for global defined types
12197 * the local name of the element is equal to the NCName of the type,
12198 * for local defined types it makes no sense to output the internal
12199 * computed name of the type. TODO: Instead, one should attach the
12200 * struct of the type involved to the error handler - this allows
12201 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000012202 */
12203static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012204xmlSchemaValidateComplexType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12205{
Daniel Veillard4255d502002-04-16 15:50:10 +000012206 xmlNodePtr child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012207 xmlSchemaTypePtr type;
12208 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012209 const xmlChar *nsUri;
Daniel Veillard3646d642004-06-02 19:19:14 +000012210
Daniel Veillard4255d502002-04-16 15:50:10 +000012211 child = ctxt->node;
12212 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012213 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000012214
Daniel Veillard4255d502002-04-16 15:50:10 +000012215 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012216 case XML_SCHEMA_CONTENT_EMPTY: {
12217 /*
12218 * 1 If the {content type} is empty, then the element information
12219 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000012220 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012221 /* TODO: Hmm, Xerces reports nodes like Comment to be invalid
12222 * content, but XSV does not.
12223 */
12224 /*
12225 * TODO: Is the entity stuff correct?
12226 */
12227 while (child != NULL) {
12228 if ((child->type == XML_ELEMENT_NODE) ||
12229 /*
12230 * TODO: Ask Daniel if this are all character nodes.
12231 */
12232 (child->type == XML_TEXT_NODE) ||
12233 (child->type == XML_CDATA_SECTION_NODE) ||
12234 (child->type == XML_ENTITY_REF_NODE) ||
12235 (child->type == XML_ENTITY_NODE)) {
12236 break;
12237 }
12238 child = child->next;
12239 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012240 if (child != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012241 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
12242 "Character or element children are not allowed, "
12243 "because the content type is empty.\n",
12244 NULL, NULL);
12245 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012246 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012247 }
12248 case XML_SCHEMA_CONTENT_ELEMENTS:
12249 case XML_SCHEMA_CONTENT_MIXED:
12250 while (child != NULL) {
12251 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012252 if (child->ns != NULL)
12253 nsUri = child->ns->href;
12254 else
12255 nsUri = NULL;
12256 ret = xmlRegExecPushString2(ctxt->regexp,
12257 child->name, nsUri, child);
12258#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000012259 if (ret < 0)
12260 xmlGenericError(xmlGenericErrorContext,
12261 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000012262 else
12263 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012264 " --> %s\n", child->name);
12265#endif
12266 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
12267 /*
12268 * TODO: Ask Daniel if this are all character nodes.
12269 */
12270 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
12271 (child->type == XML_ENTITY_NODE) ||
12272 (child->type == XML_ENTITY_REF_NODE) ||
12273 (child->type == XML_CDATA_SECTION_NODE))) {
12274 /*
12275 * 2.3 If the {content type} is element-only, then the
12276 * element information item has no character information
12277 * item [children] other than those whose [character
12278 * code] is defined as a white space in [XML 1.0 (Second
12279 * Edition)].
12280 */
12281 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
12282 "Character children are not allowed, "
12283 "because the content type is element-only.\n",
12284 NULL, NULL);
12285 break;
12286 }
12287 child = child->next;
12288 }
12289 break;
12290 case XML_SCHEMA_CONTENT_SIMPLE:
12291 case XML_SCHEMA_CONTENT_BASIC:{
12292 xmlSchemaTypePtr base, anyType;
12293 xmlChar *value = NULL;
12294 /*
12295 * We hit a complexType with a simpleContent resolving
12296 * to a user derived or built-in simple type.
12297 */
12298 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12299 /*
12300 * Internal check for integrity of the base type.
12301 */
12302 base = type->baseType;
12303 while ((base != NULL) &&
12304 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
12305 (base->type != XML_SCHEMA_TYPE_BASIC) &&
12306 (base != anyType)) {
12307 base = base->baseType;
12308 }
12309 if ((base == NULL) ||
12310 (((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) &&
12311 (base->type != XML_SCHEMA_TYPE_SIMPLE)) ||
12312 ((type->contentType == XML_SCHEMA_CONTENT_BASIC) &&
12313 (base->type != XML_SCHEMA_TYPE_BASIC)))) {
12314 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12315 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012316 "Element '%s': The base type of the corresponding "
12317 "complex type '%s' is not a user derived or a "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012318 "built-in simple type.\n",
12319 node->name, type->name);
12320 return (-1);
12321 }
12322 /*
12323 * 2.2 If the {content type} is a simple type definition,
12324 * then the element information item has no element
12325 * information item [children], and the ·normalized value·
12326 * of the element information item is ·valid· with respect
12327 * to that simple type definition as defined by String
12328 * Valid (§3.14.4).
12329 */
12330 child = node->children;
12331 while (child != NULL) {
12332 if (child->type == XML_ELEMENT_NODE) {
12333 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
12334 "Element children are not allowed, because "
12335 "the content type is a simple type.\n",
12336 NULL, NULL);
12337 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
12338 break;
12339 }
12340 child = child->next;
12341 }
12342 if (ret == 0) {
12343 /*
12344 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000012345 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012346 if (ctxt->node == NULL)
12347 value = NULL;
12348 else
12349 value = xmlNodeGetContent(node);
12350 ctxt->type = base;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012351 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012352 ctxt->type = type;
12353 if (ret > 0) {
12354 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
12355 "The character value "
12356 "is not valid with respect to the simple type.\n",
12357 NULL, NULL);
12358 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
12359 } else if (ret < 0) {
12360 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12361 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012362 "Element '%s': Error while validating character "
12363 "content against complex type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 node->name, type->name);
12365 return (-1);
12366 }
12367 }
12368 if (ret == 0) {
12369 /*
12370 * Apply facets of the complexType. Be sure to pass the
12371 * built-in type to xmlSchemaValidateFacetsInternal.
12372 */
12373 /* TODO: I don't know yet if the facets of the simple type
12374 * are used, or if the facets, defined by this complex type,
12375 * are to be used only. This here applies both facet sets.
12376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012377
12378 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
12379 value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 if (ret > 0) {
12381 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
12382 "The character value "
12383 "is not valid with respect to the simple type.\n",
12384 NULL, NULL);
12385 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
12386 } else if (ret < 0) {
12387 xmlSchemaVErr(ctxt, ctxt->cur, XML_SCHEMAS_ERR_INTERNAL,
12388 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012389 "Element '%s': Error while validating character "
12390 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012391 "apply facets.\n",
12392 type->name, NULL);
12393 }
12394 }
12395 if (value != NULL)
12396 xmlFree(value);
12397 /* TODO: facets */
12398 break;
12399 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012400 default:
12401 TODO xmlGenericError(xmlGenericErrorContext,
12402 "unimplemented content type %d\n",
12403 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000012404 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405 ctxt->cur = node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012406 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012407}
12408
12409/**
12410 * xmlSchemaValidateContent:
12411 * @ctxt: a schema validation context
12412 * @elem: an element
12413 * @type: the type declaration
12414 *
12415 * Validate the content of an element against the type.
12416 *
12417 * Returns 0 if the element is schemas valid, a positive error code
12418 * number otherwise and -1 in case of internal or API error.
12419 */
12420static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012421xmlSchemaValidateContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node)
12422{
Daniel Veillard4255d502002-04-16 15:50:10 +000012423 xmlSchemaTypePtr type;
12424
Daniel Veillard4255d502002-04-16 15:50:10 +000012425 type = ctxt->type;
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012426 ctxt->cur = node;
Daniel Veillard4255d502002-04-16 15:50:10 +000012427
12428 switch (type->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012429 case XML_SCHEMA_TYPE_ANY:
Daniel Veillardc0826a72004-08-10 14:17:33 +000012430 xmlSchemaValidateAny(ctxt);
12431 ctxt->type = type;
12432 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012433 case XML_SCHEMA_TYPE_COMPLEX:
12434 xmlSchemaValidateComplexType(ctxt, node);
12435 break;
12436 case XML_SCHEMA_TYPE_ELEMENT:{
12437 xmlSchemaElementPtr decl = (xmlSchemaElementPtr) type;
12438
12439 /*
12440 * Handle element reference here
12441 */
12442 if (decl->ref != NULL) {
12443 if (decl->refDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000012444 xmlSchemaVErr(ctxt, node, XML_SCHEMAS_ERR_INTERNAL,
12445 "Internal error: element reference %s "
12446 "not resolved\n", decl->ref, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012447 return (-1);
12448 }
12449 ctxt->type = (xmlSchemaTypePtr) decl->refDecl;
12450 decl = decl->refDecl;
12451 }
William M. Bracke7091952004-05-11 15:09:58 +000012452 /* TODO: Should "xmlSchemaValidateElement" be called instead? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012453 xmlSchemaValidateElementType(ctxt, node);
12454 ctxt->type = type;
12455 break;
12456 }
12457 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012458 case XML_SCHEMA_TYPE_SIMPLE:
12459 xmlSchemaValidateSimpleTypeElement(ctxt, node);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012460 break;
12461 case XML_SCHEMA_TYPE_FACET:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012462 TODO break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012463 case XML_SCHEMA_TYPE_SEQUENCE:
12464 TODO break;
12465 case XML_SCHEMA_TYPE_CHOICE:
12466 TODO break;
12467 case XML_SCHEMA_TYPE_ALL:
12468 TODO break;
12469 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12470 TODO break;
12471 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12472 TODO break;
12473 case XML_SCHEMA_TYPE_UR:
12474 TODO break;
12475 case XML_SCHEMA_TYPE_RESTRICTION:
12476 /*xmlSchemaValidateRestrictionType(ctxt, node); */
12477 TODO break;
12478 case XML_SCHEMA_TYPE_EXTENSION:
12479 TODO break;
12480 case XML_SCHEMA_TYPE_ATTRIBUTE:
12481 TODO break;
12482 case XML_SCHEMA_TYPE_GROUP:
12483 TODO break;
12484 case XML_SCHEMA_TYPE_NOTATION:
12485 TODO break;
12486 case XML_SCHEMA_TYPE_LIST:
12487 TODO break;
12488 case XML_SCHEMA_TYPE_UNION:
12489 TODO break;
12490 case XML_SCHEMA_FACET_MININCLUSIVE:
12491 TODO break;
12492 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12493 TODO break;
12494 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12495 TODO break;
12496 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12497 TODO break;
12498 case XML_SCHEMA_FACET_TOTALDIGITS:
12499 TODO break;
12500 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12501 TODO break;
12502 case XML_SCHEMA_FACET_PATTERN:
12503 TODO break;
12504 case XML_SCHEMA_FACET_ENUMERATION:
12505 TODO break;
12506 case XML_SCHEMA_FACET_WHITESPACE:
12507 TODO break;
12508 case XML_SCHEMA_FACET_LENGTH:
12509 TODO break;
12510 case XML_SCHEMA_FACET_MAXLENGTH:
12511 TODO break;
12512 case XML_SCHEMA_FACET_MINLENGTH:
12513 TODO break;
12514 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
12515 TODO break;
William M. Brack29aa7722004-05-12 00:27:56 +000012516 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
12517 TODO break;
Daniel Veillard4255d502002-04-16 15:50:10 +000012518 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012519
12520 if (ctxt->node == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012521 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012522 ctxt->node = ctxt->node->next;
12523 ctxt->type = type->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012524 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012525}
12526
12527/**
12528 * xmlSchemaValidateType:
12529 * @ctxt: a schema validation context
12530 * @elem: an element
12531 * @type: the list of type declarations
12532 *
12533 * Validate the content of an element against the types.
12534 *
12535 * Returns 0 if the element is schemas valid, a positive error code
12536 * number otherwise and -1 in case of internal or API error.
12537 */
12538static int
12539xmlSchemaValidateType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012540 xmlSchemaElementPtr elemDecl, xmlSchemaTypePtr type)
12541{
Daniel Veillard4255d502002-04-16 15:50:10 +000012542 xmlChar *nil;
12543
Daniel Veillard2db8c122003-07-08 12:16:59 +000012544 if ((elem == NULL) || (type == NULL) || (elemDecl == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012545 return (0);
Daniel Veillard2db8c122003-07-08 12:16:59 +000012546
Daniel Veillard3646d642004-06-02 19:19:14 +000012547 /* This one is called by "xmlSchemaValidateElementType" and
12548 * "xmlSchemaValidateElement".
12549 */
12550
Daniel Veillard4255d502002-04-16 15:50:10 +000012551 /*
12552 * 3.3.4 : 2
12553 */
12554 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
William M. Bracke7091952004-05-11 15:09:58 +000012555 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
12556 "Element declaration %s is abstract\n",
12557 elemDecl->name, NULL);
12558 /* Changed, since the element declaration is abstract and not
12559 * the element itself. */
12560 /* xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_ISABSTRACT,
12561 "Element %s is abstract\n", elem->name, NULL); */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012562 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012563 }
12564 /*
12565 * 3.3.4: 3
12566 */
12567 nil = xmlGetNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
12568 if (elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012569 /* 3.3.4: 3.2 */
12570 if (xmlStrEqual(nil, BAD_CAST "true")) {
12571 if (elem->children != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000012572 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTEMPTY,
12573 "Element %s is not empty\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012574 return (ctxt->err);
12575 }
12576 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
12577 (elemDecl->value != NULL)) {
William M. Bracke7091952004-05-11 15:09:58 +000012578 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_HAVEDEFAULT,
12579 "Empty element %s cannot get a fixed value\n",
12580 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012581 return (ctxt->err);
12582 }
12583 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012584 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012585 /* 3.3.4: 3.1 */
12586 if (nil != NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000012587 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTNILLABLE,
12588 "Element %s with xs:nil but not nillable\n",
12589 elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012590 xmlFree(nil);
12591 return (ctxt->err);
12592 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012593 }
12594
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012595 /* TODO 3.3.4: 4 if the element carries xs:type */
Daniel Veillard4255d502002-04-16 15:50:10 +000012596
12597 ctxt->type = elemDecl->subtypes;
12598 ctxt->node = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012599 xmlSchemaValidateContent(ctxt, elem);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012600 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012601}
12602
12603
12604/**
12605 * xmlSchemaValidateAttributes:
12606 * @ctxt: a schema validation context
12607 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000012608 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000012609 *
12610 * Validate the attributes of an element.
12611 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000012612 * 1. Existent, invalid attributes are reported in the form
12613 * "prefix:localName".
12614 * Reason: readability - it is easier to find the actual XML
12615 * representation of the attributes QName.
12616 * 2. Missing attributes are reported in the form
12617 * {"URI", "localName"}.
12618 * This is necessary, since the the prefix need not to be declared
12619 * at all, and thus is not computable.
12620 *
Daniel Veillard4255d502002-04-16 15:50:10 +000012621 * Returns 0 if the element is schemas valid, a positive error code
12622 * number otherwise and -1 in case of internal or API error.
12623 */
12624static int
Daniel Veillard3646d642004-06-02 19:19:14 +000012625xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012626{
Daniel Veillard3646d642004-06-02 19:19:14 +000012627 int ret;
12628 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000012629 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012630 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000012631 xmlSchemaAttributeLinkPtr attrUse;
12632 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000012633 int found;
William M. Brack803812b2004-06-03 02:11:24 +000012634 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012635#ifdef DEBUG_ATTR_VALIDATION
12636 int redundant = 0;
12637#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012638
Daniel Veillardc0826a72004-08-10 14:17:33 +000012639 /*
12640 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
12641 * if we have an attribute reference or an attribute declaration.
12642 */
12643 /*
12644 * Allow all attributes if the type is anyType.
12645 */
12646 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
12647 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012648 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000012649 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000012650 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012651 attrDecl = attrUse->attr;
12652#ifdef DEBUG_ATTR_VALIDATION
12653 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
12654 printf("attr use - use: %d\n", attrDecl->occurs);
12655#endif
12656 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
12657
12658 if (curState->decl == attrUse->attr) {
12659#ifdef DEBUG_ATTR_VALIDATION
12660 redundant = 1;
12661#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012662 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012663 attr = curState->attr;
12664#ifdef DEBUG_ATTR_VALIDATION
12665 printf("attr - name: %s\n", attr->name);
12666 if (attr->ns != NULL)
12667 printf("attr - ns: %s\n", attr->ns->href);
12668 else
12669 printf("attr - ns: none\n");
12670#endif
12671 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012672 if (attr == NULL)
12673 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012674 if (attrDecl->ref != NULL) {
12675 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012676 continue;
12677 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012678 if ((attrDecl->refNs == NULL) ||
12679 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012680 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012681 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012682 continue;
12683 }
12684 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000012685 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012686 continue;
12687 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012688 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012689 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012690 if (attr->ns == NULL) {
12691 /*
William M. Bracke7091952004-05-11 15:09:58 +000012692 * accept an unqualified attribute only if the target
12693 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012694 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012695 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000012696 /*
12697 * This check was removed, since the target namespace
12698 * was evaluated during parsing and already took
12699 * "attributeFormDefault" into account.
12700 */
12701 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012702 continue;
12703 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000012704 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012705 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012706 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012707 attr->ns->href))
12708 continue;
12709 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012710 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012711#ifdef DEBUG_ATTR_VALIDATION
12712 printf("found\n");
12713#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000012714 found = 1;
Daniel Veillard50355f02004-06-08 17:52:16 +000012715 ctxt->cur = (xmlNodePtr) attr;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012716 ctxt->node = attr->children;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000012717
Daniel Veillard3646d642004-06-02 19:19:14 +000012718 if (attrDecl->subtypes == NULL) {
12719 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
12720 curState->decl = attrDecl;
William M. Bracke7091952004-05-11 15:09:58 +000012721 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAS_ERR_INTERNAL,
12722 "Internal error: attribute %s type not resolved\n",
12723 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012724 continue;
12725 }
12726 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012727 ctxt->type = attrDecl->subtypes;
12728 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012729 ctxt->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +000012730 if (ret != 0)
12731 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
12732 else
12733 curState->state = XML_SCHEMAS_ATTR_CHECKED;
12734 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012735 if (value != NULL) {
12736 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000012737 }
12738 }
12739 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12740 xmlSchemaAttrStatePtr tmp;
12741
12742#ifdef DEBUG_ATTR_VALIDATION
12743 printf("required attr not found\n");
12744#endif
12745 /*
12746 * Add a new dummy attribute state.
12747 */
12748 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
12749 if (tmp == NULL) {
12750 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
12751 return (-1);
12752 }
12753 tmp->attr = NULL;
12754 tmp->state = XML_SCHEMAS_ATTR_MISSING;
12755 tmp->decl = attrDecl;
12756 tmp->next = NULL;
12757
12758 if (reqAttrStates == NULL) {
12759 reqAttrStates = tmp;
12760 reqAttrStatesTop = tmp;
12761 } else {
12762 reqAttrStatesTop->next = tmp;
12763 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012764 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012765
12766 }
12767 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000012768 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012769 /*
12770 * Add required attributes to the attribute states of the context.
12771 */
12772 if (reqAttrStates != NULL) {
12773 if (ctxt->attr == NULL) {
12774 ctxt->attr = reqAttrStates;
12775 } else {
12776 ctxt->attrTop->next = reqAttrStates;
12777 }
12778 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012779 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012780 /*
12781 * Process wildcards.
12782 */
12783 if (type->attributeWildcard != NULL) {
12784#ifdef DEBUG_ATTR_VALIDATION
12785 xmlSchemaWildcardNsPtr ns;
12786 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012787 if (type->attributeWildcard->processContents ==
12788 XML_SCHEMAS_ANY_LAX)
12789 printf("processContents: lax\n");
12790 else if (type->attributeWildcard->processContents ==
12791 XML_SCHEMAS_ANY_STRICT)
12792 printf("processContents: strict\n");
12793 else
12794 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000012795 if (type->attributeWildcard->any)
12796 printf("type: any\n");
12797 else if (type->attributeWildcard->negNsSet != NULL) {
12798 printf("type: negated\n");
12799 if (type->attributeWildcard->negNsSet->value == NULL)
12800 printf("ns: (absent)\n");
12801 else
12802 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
12803 } else if (type->attributeWildcard->nsSet != NULL) {
12804 printf("type: set\n");
12805 ns = type->attributeWildcard->nsSet;
12806 while (ns != NULL) {
12807 if (ns->value == NULL)
12808 printf("ns: (absent)\n");
12809 else
12810 printf("ns: %s\n", ns->value);
12811 ns = ns->next;
12812 }
12813 } else
12814 printf("empty\n");
12815
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012816
12817#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000012818 curState = ctxt->attr;
12819 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012820 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
12821 if (curState->attr->ns != NULL)
12822 nsURI = curState->attr->ns->href;
12823 else
12824 nsURI = NULL;
12825 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12826 nsURI)) {
12827 /*
12828 * Handle processContents.
12829 */
12830 if ((type->attributeWildcard->processContents ==
12831 XML_SCHEMAS_ANY_LAX) ||
12832 (type->attributeWildcard->processContents ==
12833 XML_SCHEMAS_ANY_STRICT)) {
12834
12835 attr = curState->attr;
12836 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
12837 attr->name, nsURI);
12838 if (attrDecl != NULL) {
12839 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012840 ctxt->cur = (xmlNodePtr) attr;
12841 ctxt->node = attr->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012842 ctxt->type = attrDecl->subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012843 ret = xmlSchemaValidateSimpleTypeValue(ctxt, value, 1, 1, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012844 ctxt->type = type;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012845 if (ret != 0)
12846 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
12847 else
12848 curState->state = XML_SCHEMAS_ATTR_CHECKED;
12849 curState->decl = attrDecl;
12850 if (value != NULL) {
12851 xmlFree(value);
12852 }
12853
12854 } else if (type->attributeWildcard->processContents ==
12855 XML_SCHEMAS_ANY_LAX) {
12856 curState->state = XML_SCHEMAS_ATTR_CHECKED;
12857 }
12858 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000012860 }
12861 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012862 curState = curState->next;
12863 }
12864 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012865 /*
12866 * Report missing and illegal attributes.
12867 */
12868 if (ctxt->attr != NULL) {
12869 curState = ctxt->attr;
12870 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
12871 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
12872 attr = curState->attr;
12873 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
12874 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
12875 else if ((curState->state == XML_SCHEMAS_ATTR_UNKNOWN) ||
12876 /* TODO: "prohibited" won't ever be touched!. */
12877 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
12878 xmlSchemaVIllegalAttrErr(ctxt, attr);
12879 }
12880 curState = curState->next;
12881 }
12882 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012883#ifdef DEBUG_ATTR_VALIDATION
12884 if (redundant)
12885 xmlGenericError(xmlGenericErrorContext,
12886 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
12887 type->name);
12888#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012889 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012890}
12891
12892/**
12893 * xmlSchemaValidateElement:
12894 * @ctxt: a schema validation context
12895 * @elem: an element
12896 *
12897 * Validate an element in a tree
12898 *
12899 * Returns 0 if the element is schemas valid, a positive error code
12900 * number otherwise and -1 in case of internal or API error.
12901 */
12902static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012903xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
12904{
Daniel Veillard4255d502002-04-16 15:50:10 +000012905 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000012906 int ret;
12907 xmlSchemaAttrStatePtr attrs, attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000012908
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012909 if (elem->ns != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012910 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
12911 elem->name, elem->ns->href, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012912 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012913 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
12914 elem->name, NULL, NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012915 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012916 /*
12917 * This one is called by xmlSchemaValidateDocument and
12918 * xmlSchemaValidateAnyInernal.
12919 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000012920
Daniel Veillard4255d502002-04-16 15:50:10 +000012921 /*
12922 * 3.3.4 : 1
12923 */
12924 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000012925 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_UNDECLAREDELEM,
12926 "Element %s not declared\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012927 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012928 }
12929 if (elemDecl->subtypes == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000012930 xmlSchemaVErr(ctxt, elem, XML_SCHEMAS_ERR_NOTYPE,
12931 "Element %s has no type\n", elem->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012932 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012933 }
12934 /*
12935 * Verify the attributes
12936 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012937 attrs = ctxt->attr;
12938 attrTop = ctxt->attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000012939 xmlSchemaRegisterAttributes(ctxt, elem->properties);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012940 xmlSchemaValidateAttributes(ctxt, elem, elemDecl->subtypes);
12941 if (ctxt->attr != NULL)
12942 xmlSchemaFreeAttributeStates(ctxt->attr);
12943 ctxt->attr = attrs;
12944 ctxt->attrTop = attrTop;
Daniel Veillard4255d502002-04-16 15:50:10 +000012945 /*
12946 * Verify the element content recursively
12947 */
12948 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012949 ctxt->regexp = xmlRegNewExecCtxt(elemDecl->contModel,
12950 (xmlRegExecCallbacks)
12951 xmlSchemaValidateCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012952#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012953 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012954#endif
12955 }
12956 xmlSchemaValidateType(ctxt, elem, elemDecl, elemDecl->subtypes);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012957 if (elemDecl->contModel != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012958 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012959#ifdef DEBUG_AUTOMATA
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012960 xmlGenericError(xmlGenericErrorContext,
12961 "====> %s : %d\n", elem->name, ret);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012962#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000012963 if (ret == 0) {
12964 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
12965 elem, "The element content is not valid", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012966 } else if (ret < 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012967 xmlSchemaVCustomErr(ctxt, XML_SCHEMAS_ERR_ELEMCONT,
12968 elem, "The element content is not valid", NULL);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012969#ifdef DEBUG_CONTENT
Daniel Veillardc0826a72004-08-10 14:17:33 +000012970 else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012971 xmlGenericError(xmlGenericErrorContext,
12972 "Element %s content check succeeded\n",
12973 elem->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000012974
12975#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012976 }
12977 xmlRegFreeExecCtxt(ctxt->regexp);
Daniel Veillard4255d502002-04-16 15:50:10 +000012978 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012979 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000012980}
12981
12982/**
12983 * xmlSchemaValidateDocument:
12984 * @ctxt: a schema validation context
12985 * @doc: a parsed document tree
12986 *
12987 * Validate a document tree in memory.
12988 *
12989 * Returns 0 if the document is schemas valid, a positive error code
12990 * number otherwise and -1 in case of internal or API error.
12991 */
12992static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012993xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
12994{
Daniel Veillard4255d502002-04-16 15:50:10 +000012995 xmlNodePtr root;
12996 xmlSchemaElementPtr elemDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012997
Daniel Veillard4255d502002-04-16 15:50:10 +000012998 root = xmlDocGetRootElement(doc);
12999 if (root == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013000 xmlSchemaVErr(ctxt, (xmlNodePtr) doc, XML_SCHEMAS_ERR_NOROOT,
13001 "document has no root\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013002 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013003 }
William M. Bracke7091952004-05-11 15:09:58 +000013004
Daniel Veillard4255d502002-04-16 15:50:10 +000013005 if (root->ns != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013006 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13007 root->name, root->ns->href, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013008 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013009 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13010 root->name, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013011
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013012 /*
13013 * special case whe elementFormDefault is unqualified for top-level elem.
13014 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013015 /* Removed, since elementFormDefault does not apply to top level
13016 * elements */
13017 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013018 if ((elemDecl == NULL) && (root->ns != NULL) &&
13019 (xmlStrEqual(ctxt->schema->targetNamespace, root->ns->href)) &&
13020 ((ctxt->schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0)) {
13021 elemDecl = xmlHashLookup3(ctxt->schema->elemDecl,
13022 root->name, NULL, NULL);
13023 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013024 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000013025
Daniel Veillard4255d502002-04-16 15:50:10 +000013026 if (elemDecl == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +000013027 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_UNDECLAREDELEM,
13028 "Element %s not declared\n", root->name, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013029 } else if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
William M. Bracke7091952004-05-11 15:09:58 +000013030 xmlSchemaVErr(ctxt, root, XML_SCHEMAS_ERR_NOTTOPLEVEL,
Daniel Veillard3646d642004-06-02 19:19:14 +000013031 "Root element %s not global\n", root->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013032 }
13033 /*
13034 * Okay, start the recursive validation
13035 */
13036 xmlSchemaValidateElement(ctxt, root);
13037
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013038 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000013039}
13040
13041/************************************************************************
13042 * *
13043 * SAX Validation code *
13044 * *
13045 ************************************************************************/
13046
13047/************************************************************************
13048 * *
13049 * Validation interfaces *
13050 * *
13051 ************************************************************************/
13052
13053/**
13054 * xmlSchemaNewValidCtxt:
13055 * @schema: a precompiled XML Schemas
13056 *
13057 * Create an XML Schemas validation context based on the given schema
13058 *
13059 * Returns the validation context or NULL in case of error
13060 */
13061xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013062xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
13063{
Daniel Veillard4255d502002-04-16 15:50:10 +000013064 xmlSchemaValidCtxtPtr ret;
13065
13066 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
13067 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013068 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013069 return (NULL);
13070 }
13071 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013072 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000013073 ret->attrTop = NULL;
13074 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013075 return (ret);
13076}
13077
13078/**
13079 * xmlSchemaFreeValidCtxt:
13080 * @ctxt: the schema validation context
13081 *
13082 * Free the resources associated to the schema validation context
13083 */
13084void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013085xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
13086{
Daniel Veillard4255d502002-04-16 15:50:10 +000013087 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013088 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013089 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013090 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000013091 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013092 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000013093 xmlFree(ctxt);
13094}
13095
13096/**
13097 * xmlSchemaSetValidErrors:
13098 * @ctxt: a schema validation context
13099 * @err: the error function
13100 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000013101 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000013102 *
13103 * Set the error and warning callback informations
13104 */
13105void
13106xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013107 xmlSchemaValidityErrorFunc err,
13108 xmlSchemaValidityWarningFunc warn, void *ctx)
13109{
Daniel Veillard4255d502002-04-16 15:50:10 +000013110 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013111 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013112 ctxt->error = err;
13113 ctxt->warning = warn;
13114 ctxt->userData = ctx;
13115}
13116
13117/**
13118 * xmlSchemaValidateDoc:
13119 * @ctxt: a schema validation context
13120 * @doc: a parsed document tree
13121 *
13122 * Validate a document tree in memory.
13123 *
13124 * Returns 0 if the document is schemas valid, a positive error code
13125 * number otherwise and -1 in case of internal or API error.
13126 */
13127int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013128xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
13129{
Daniel Veillard4255d502002-04-16 15:50:10 +000013130 int ret;
13131
13132 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013133 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013134
13135 ctxt->doc = doc;
13136 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013137 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000013138}
13139
13140/**
13141 * xmlSchemaValidateStream:
13142 * @ctxt: a schema validation context
13143 * @input: the input to use for reading the data
13144 * @enc: an optional encoding information
13145 * @sax: a SAX handler for the resulting events
13146 * @user_data: the context to provide to the SAX handler.
13147 *
13148 * Validate a document tree in memory.
13149 *
13150 * Returns 0 if the document is schemas valid, a positive error code
13151 * number otherwise and -1 in case of internal or API error.
13152 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013153int
Daniel Veillard4255d502002-04-16 15:50:10 +000013154xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013155 xmlParserInputBufferPtr input, xmlCharEncoding enc,
13156 xmlSAXHandlerPtr sax, void *user_data)
13157{
Daniel Veillard4255d502002-04-16 15:50:10 +000013158 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013159 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013160 ctxt->input = input;
13161 ctxt->enc = enc;
13162 ctxt->sax = sax;
13163 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013164 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013165}
13166
13167#endif /* LIBXML_SCHEMAS_ENABLED */