blob: 187850563c13581a637f08945bcd2b1f1e6ce99a [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000037
Daniel Veillarda84c0b32003-06-02 16:58:46 +000038/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000039
Daniel Veillard82bbbd42003-05-11 20:16:09 +000040/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000041
Daniel Veillard82bbbd42003-05-11 20:16:09 +000042/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000043
Daniel Veillard118aed72002-09-24 14:13:13 +000044/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000045
Daniel Veillard4255d502002-04-16 15:50:10 +000046/* #define DEBUG_AUTOMATA 1 */
47
Daniel Veillard3646d642004-06-02 19:19:14 +000048/* #define DEBUG_ATTR_VALIDATION 1 */
49
Daniel Veillardc0826a72004-08-10 14:17:33 +000050/* #define DEBUG_UNION_VALIDATION 1 */
51
52
Daniel Veillard4255d502002-04-16 15:50:10 +000053#define UNBOUNDED (1 << 30)
54#define TODO \
55 xmlGenericError(xmlGenericErrorContext, \
56 "Unimplemented block at %s:%d\n", \
57 __FILE__, __LINE__);
58
William M. Brack2f2a6632004-08-20 23:09:47 +000059#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000060
Daniel Veillard4255d502002-04-16 15:50:10 +000061/*
62 * The XML Schemas namespaces
63 */
64static const xmlChar *xmlSchemaNs = (const xmlChar *)
65 "http://www.w3.org/2001/XMLSchema";
66
67static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
68 "http://www.w3.org/2001/XMLSchema-instance";
69
Daniel Veillardc0826a72004-08-10 14:17:33 +000070static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
71 "Element decl.";
72static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
73 "Element ref.";
74static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
75 "Attribute decl.";
76static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
77 "Attribute ref.";
78static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
79 "ST";
80static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
81 "CT";
82
Daniel Veillard4255d502002-04-16 15:50:10 +000083#define IS_SCHEMA(node, type) \
84 ((node != NULL) && (node->ns != NULL) && \
85 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
86 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
87
Daniel Veillardc0826a72004-08-10 14:17:33 +000088#define FREE_AND_NULL(str) \
89 if (str != NULL) { \
90 xmlFree(str); \
91 str = NULL; \
92 }
93
94#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
95#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
96#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
97
Daniel Veillard4255d502002-04-16 15:50:10 +000098#define XML_SCHEMAS_PARSE_ERROR 1
99
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000100#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
101
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000102/*
103 * xmlSchemaValidOption:
104 *
105 * This is the set of XML Schema validation options.
106 */
107typedef enum {
108 XML_SCHEMA_VAL_XSI_ASSEMBLE = 1<<0
109 /* assemble schemata using
110 * xsi:schemaLocation and
111 * xsi:noNamespaceSchemaLocation */
112
113} xmlSchemaValidOption;
114
115/*
116* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
117* allow to assemble schemata with
118* the same target namespace from
119* different sources; otherwise, the first
120* encountered schema with a specific target
121* namespace will be used only *
122
123*
124* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
125* locate schemata to be imported
126* using the namespace name; otherwise
127* the location URI will be used */
128
129/*
130* xmlSchemaParserOption:
131*
132* This is the set of XML Schema parser options.
133*/
134typedef enum {
135 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
136 /* locate schemata to be imported
137 * using the namespace name; otherwise
138 * the location URI will be used */
139} xmlSchemaParserOption;
140
141/*
142XMLPUBFUN int XMLCALL
143 xmlSchemaValidCtxtSetOptions(xmlSchemaValidCtxtPtr ctxt,
144 int options);
145XMLPUBFUN int XMLCALL
146 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
149 int options);
150XMLPUBFUN int XMLCALL
151 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
152
153*/
154
155typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
156typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
157struct _xmlSchemaAssemble {
158 void *items; /* used for dynamic addition of schemata */
159 int nbItems; /* used for dynamic addition of schemata */
160 int sizeItems; /* used for dynamic addition of schemata */
161};
162
Daniel Veillard4255d502002-04-16 15:50:10 +0000163struct _xmlSchemaParserCtxt {
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 Veillarde19fc232002-04-22 16:01:24 +0000167 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000168 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000169 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000170
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000171 xmlSchemaPtr topschema; /* The main schema */
172 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
173
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000174 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000176 int counter;
177
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000178 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000180 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000181
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182 const char *buffer;
183 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000184
Daniel Veillard4255d502002-04-16 15:50:10 +0000185 /*
186 * Used to build complex element content models
187 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000188 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000189 xmlAutomataStatePtr start;
190 xmlAutomataStatePtr end;
191 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000192
193 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000194 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000195 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
196 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000197 xmlSchemaAssemblePtr assemble;
198 int options;
Daniel Veillard4255d502002-04-16 15:50:10 +0000199};
200
201
202#define XML_SCHEMAS_ATTR_UNKNOWN 1
203#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000204#define XML_SCHEMAS_ATTR_PROHIBITED 3
205#define XML_SCHEMAS_ATTR_MISSING 4
206#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
207#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Daniel Veillard4255d502002-04-16 15:50:10 +0000208
209typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
210typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
211struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000212 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 xmlAttrPtr attr;
214 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000215 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +0000216};
217
218/**
219 * xmlSchemaValidCtxt:
220 *
221 * A Schemas validation context
222 */
223
224struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000225 void *userData; /* user specific data block */
226 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
227 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000228 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
231 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000233 xmlCharEncoding enc;
234 xmlSAXHandlerPtr sax;
235 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000236
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000237 xmlDocPtr myDoc;
238 int err;
239 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000240
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000241 xmlNodePtr node;
242 xmlNodePtr cur;
243 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000244
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000245 xmlRegExecCtxtPtr regexp;
246 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000247
Daniel Veillard3646d642004-06-02 19:19:14 +0000248 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000249 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000250 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000251 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000252 int options;
Daniel Veillard4255d502002-04-16 15:50:10 +0000253};
254
Daniel Veillard1d913862003-11-21 00:28:39 +0000255/*
256 * These are the entries in the schemas importSchemas hash table
257 */
258typedef struct _xmlSchemaImport xmlSchemaImport;
259typedef xmlSchemaImport *xmlSchemaImportPtr;
260struct _xmlSchemaImport {
261 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000262 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000263 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000264 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000265};
Daniel Veillard4255d502002-04-16 15:50:10 +0000266
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000267/*
268 * These are the entries associated to includes in a schemas
269 */
270typedef struct _xmlSchemaInclude xmlSchemaInclude;
271typedef xmlSchemaInclude *xmlSchemaIncludePtr;
272struct _xmlSchemaInclude {
273 xmlSchemaIncludePtr next;
274
275 const xmlChar *schemaLocation;
276 xmlDocPtr doc;
277};
278
Daniel Veillard4255d502002-04-16 15:50:10 +0000279/************************************************************************
280 * *
281 * Some predeclarations *
282 * *
283 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000284
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000285static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
286 xmlSchemaPtr schema,
287 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000288static void
289xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
290 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
291static const char *
292xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
293static int
294xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000295 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000296 const xmlChar *value,
297 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000298 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000299 int normalize,
300 int checkNodes);
301static int
302xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
303 xmlSchemaElementPtr elemDecl);
304static int
305xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
306 xmlSchemaTypePtr type);
307static int
308xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000309static int
310xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
311 xmlNodePtr node);
William M. Brack87640d52004-04-17 14:58:15 +0000312
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000313/************************************************************************
314 * *
315 * Datatype error handlers *
316 * *
317 ************************************************************************/
318
319/**
320 * xmlSchemaPErrMemory:
321 * @node: a context node
322 * @extra: extra informations
323 *
324 * Handle an out of memory condition
325 */
326static void
327xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
328 const char *extra, xmlNodePtr node)
329{
330 if (ctxt != NULL)
331 ctxt->nberrors++;
332 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
333 extra);
334}
335
336/**
337 * xmlSchemaPErr:
338 * @ctxt: the parsing context
339 * @node: the context node
340 * @error: the error code
341 * @msg: the error message
342 * @str1: extra data
343 * @str2: extra data
344 *
345 * Handle a parser error
346 */
347static void
348xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
349 const char *msg, const xmlChar * str1, const xmlChar * str2)
350{
351 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000352 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000353 void *data = NULL;
354
355 if (ctxt != NULL) {
356 ctxt->nberrors++;
357 channel = ctxt->error;
358 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000359 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000360 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000361 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000362 error, XML_ERR_ERROR, NULL, 0,
363 (const char *) str1, (const char *) str2, NULL, 0, 0,
364 msg, str1, str2);
365}
366
367/**
368 * xmlSchemaPErr2:
369 * @ctxt: the parsing context
370 * @node: the context node
371 * @node: the current child
372 * @error: the error code
373 * @msg: the error message
374 * @str1: extra data
375 * @str2: extra data
376 *
377 * Handle a parser error
378 */
379static void
380xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
381 xmlNodePtr child, int error,
382 const char *msg, const xmlChar * str1, const xmlChar * str2)
383{
384 if (child != NULL)
385 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
386 else
387 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
388}
389
Daniel Veillard01fa6152004-06-29 17:04:39 +0000390
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000391/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000392 * xmlSchemaPErrExt:
393 * @ctxt: the parsing context
394 * @node: the context node
395 * @error: the error code
396 * @strData1: extra data
397 * @strData2: extra data
398 * @strData3: extra data
399 * @msg: the message
400 * @str1: extra parameter for the message display
401 * @str2: extra parameter for the message display
402 * @str3: extra parameter for the message display
403 * @str4: extra parameter for the message display
404 * @str5: extra parameter for the message display
405 *
406 * Handle a parser error
407 */
408static void
409xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
410 const xmlChar * strData1, const xmlChar * strData2,
411 const xmlChar * strData3, const char *msg, const xmlChar * str1,
412 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
413 const xmlChar * str5)
414{
415
416 xmlGenericErrorFunc channel = NULL;
417 xmlStructuredErrorFunc schannel = NULL;
418 void *data = NULL;
419
420 if (ctxt != NULL) {
421 ctxt->nberrors++;
422 channel = ctxt->error;
423 data = ctxt->userData;
424 schannel = ctxt->serror;
425 }
426 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
427 error, XML_ERR_ERROR, NULL, 0,
428 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000429 (const char *) strData3, 0, 0, msg, str1, str2,
430 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000431}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000432
Daniel Veillard3646d642004-06-02 19:19:14 +0000433
434/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000435 * xmlSchemaVTypeErrMemory:
436 * @node: a context node
437 * @extra: extra informations
438 *
439 * Handle an out of memory condition
440 */
441static void
442xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
443 const char *extra, xmlNodePtr node)
444{
445 if (ctxt != NULL) {
446 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000447 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000448 }
449 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
450 extra);
451}
452
453/**
454 * xmlSchemaVErr3:
455 * @ctxt: the validation context
456 * @node: the context node
457 * @error: the error code
458 * @msg: the error message
459 * @str1: extra data
460 * @str2: extra data
461 * @str3: extra data
462 *
463 * Handle a validation error
464 */
465static void
466xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
467 const char *msg, const xmlChar *str1, const xmlChar *str2,
468 const xmlChar *str3)
469{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000470 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000471 xmlGenericErrorFunc channel = NULL;
472 void *data = NULL;
473
474 if (ctxt != NULL) {
475 ctxt->nberrors++;
476 ctxt->err = error;
477 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000478 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000479 data = ctxt->userData;
480 }
481 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000482 /* Removed, since the old schema error codes have been
483 * substituted for the global error codes.
484 *
485 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
486 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000487 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000488 error, XML_ERR_ERROR, NULL, 0,
489 (const char *) str1, (const char *) str2,
490 (const char *) str3, 0, 0,
491 msg, str1, str2, str3);
492}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000493
494/**
495 * xmlSchemaVErrExt:
496 * @ctxt: the validation context
497 * @node: the context node
498 * @error: the error code
499 * @msg: the message
500 * @str1: extra parameter for the message display
501 * @str2: extra parameter for the message display
502 * @str3: extra parameter for the message display
503 * @str4: extra parameter for the message display
504 * @str5: extra parameter for the message display
505 *
506 * Handle a validation error
507 */
508static void
509xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
510 const char *msg, const xmlChar * str1,
511 const xmlChar * str2, const xmlChar * str3,
512 const xmlChar * str4, const xmlChar * str5)
513{
514 xmlStructuredErrorFunc schannel = NULL;
515 xmlGenericErrorFunc channel = NULL;
516 void *data = NULL;
517
518 if (ctxt != NULL) {
519 ctxt->nberrors++;
520 ctxt->err = error;
521 channel = ctxt->error;
522 schannel = ctxt->serror;
523 data = ctxt->userData;
524 }
525 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000526 /* Removed, since the old schema error codes have been
527 * substituted for the global error codes.
528 *
529 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
530 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000531 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
532 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
533 msg, str1, str2, str3, str4, str5);
534}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000535/**
536 * xmlSchemaVErr:
537 * @ctxt: the validation context
538 * @node: the context node
539 * @error: the error code
540 * @msg: the error message
541 * @str1: extra data
542 * @str2: extra data
543 *
544 * Handle a validation error
545 */
546static void
547xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
548 const char *msg, const xmlChar * str1, const xmlChar * str2)
549{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000550 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000551 xmlGenericErrorFunc channel = NULL;
552 void *data = NULL;
553
554 if (ctxt != NULL) {
555 ctxt->nberrors++;
556 ctxt->err = error;
557 channel = ctxt->error;
558 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000559 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000560 }
561 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000562 /* Removed, since the old schema error codes have been
563 * substituted for the global error codes.
564 *
565 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
566 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000567 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 error, XML_ERR_ERROR, NULL, 0,
569 (const char *) str1, (const char *) str2, NULL, 0, 0,
570 msg, str1, str2);
571}
Daniel Veillard4255d502002-04-16 15:50:10 +0000572
Daniel Veillardc0826a72004-08-10 14:17:33 +0000573/**
574 * xmlSchemaGetOnymousTypeName:
575 * @attr: the attribute declaration/use
576 *
577 * Returns the name of the attribute; if the attribute
578 * is a reference, the name of the referenced global type will be returned.
579 */
580static const xmlChar *
581xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
582{
583 if (attr->ref != NULL)
584 return(attr->ref);
585 else
586 return(attr->name);
587}
588
589/**
590 * xmlSchemaGetOnymousTargetNsURI:
591 * @type: the type (element or attribute)
592 *
593 * Returns the target namespace URI of the type; if the type is a reference,
594 * the target namespace of the referenced type will be returned.
595 */
596static const xmlChar *
597xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
598{
599 if (attr->ref != NULL)
600 return (attr->refNs);
601 else
602 return(attr->targetNamespace);
603}
604
605/**
606 * xmlSchemaFormatNsUriLocal:
607 * @buf: the string buffer
608 * @uri: the namespace URI
609 * @local: the local name
610 *
611 * Returns a representation of the given URI used
612 * for error reports.
613 *
614 * Returns an empty string, if @ns is NULL, a formatted
615 * string otherwise.
616 */
617static const xmlChar*
618xmlSchemaFormatNsUriLocal(xmlChar **buf,
619 const xmlChar *uri, const xmlChar *local)
620{
621 if (*buf != NULL)
622 xmlFree(*buf);
623 if (uri == NULL) {
624 *buf = xmlStrdup(BAD_CAST "{'");
625 *buf = xmlStrcat(*buf, local);
626 } else {
627 *buf = xmlStrdup(BAD_CAST "{'");
628 *buf = xmlStrcat(*buf, uri);
629 *buf = xmlStrcat(*buf, BAD_CAST "', '");
630 *buf = xmlStrcat(*buf, local);
631 }
632 *buf = xmlStrcat(*buf, BAD_CAST "'}");
633 return ((const xmlChar *) *buf);
634}
635
636/**
637 * xmlSchemaFormatNsPrefixLocal:
638 * @buf: the string buffer
639 * @ns: the namespace
640 * @local: the local name
641 *
642 * Returns a representation of the given URI used
643 * for error reports.
644 *
645 * Returns an empty string, if @ns is NULL, a formatted
646 * string otherwise.
647 */
648static const xmlChar*
649xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
650 xmlNsPtr ns, const xmlChar *local)
651{
652 if (*buf != NULL) {
653 xmlFree(*buf);
654 *buf = NULL;
655 }
656 if ((ns == NULL) || (ns->prefix == NULL))
657 return(local);
658 else {
659 *buf = xmlStrdup(ns->prefix);
660 *buf = xmlStrcat(*buf, BAD_CAST ":");
661 *buf = xmlStrcat(*buf, local);
662 }
663 return ((const xmlChar *) *buf);
664}
665
666/**
667 * xmlSchemaFormatItemForReport:
668 * @buf: the string buffer
669 * @itemDes: the designation of the item
670 * @itemName: the name of the item
671 * @item: the item as an object
672 * @itemNode: the node of the item
673 * @local: the local name
674 * @parsing: if the function is used during the parse
675 *
676 * Returns a representation of the given item used
677 * for error reports.
678 *
679 * The following order is used to build the resulting
680 * designation if the arguments are not NULL:
681 * 1a. If itemDes not NULL -> itemDes
682 * 1b. If (itemDes not NULL) and (itemName not NULL)
683 * -> itemDes + itemName
684 * 2. If the preceding was NULL and (item not NULL) -> item
685 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
686 *
687 * If the itemNode is an attribute node, the name of the attribute
688 * will be appended to the result.
689 *
690 * Returns the formatted string and sets @buf to the resulting value.
691 */
692static xmlChar*
693xmlSchemaFormatItemForReport(xmlChar **buf,
694 const xmlChar *itemDes,
695 xmlSchemaTypePtr item,
696 xmlNodePtr itemNode,
697 int parsing)
698{
699 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000700 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000701
702 if (*buf != NULL) {
703 xmlFree(*buf);
704 *buf = NULL;
705 }
706
William M. Brack2f2a6632004-08-20 23:09:47 +0000707 if (itemDes != NULL) {
708 *buf = xmlStrdup(itemDes);
709 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000710 if (item->type == XML_SCHEMA_TYPE_BASIC) {
711 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
712 *buf = xmlStrdup(BAD_CAST "'anyType'");
713 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
714 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
715 else {
716 /* *buf = xmlStrdup(BAD_CAST "bi "); */
717 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
718 *buf = xmlStrdup(BAD_CAST "'");
719 *buf = xmlStrcat(*buf, item->name);
720 *buf = xmlStrcat(*buf, BAD_CAST "'");
721 }
722 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
723 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
724 *buf = xmlStrdup(xmlSchemaElemDesST);
725 *buf = xmlStrcat(*buf, BAD_CAST " '");
726 *buf = xmlStrcat(*buf, item->name);
727 *buf = xmlStrcat(*buf, BAD_CAST "'");
728 } else {
729 *buf = xmlStrdup(xmlSchemaElemDesST);
730 *buf = xmlStrcat(*buf, BAD_CAST " local");
731 }
732 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
733 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
734 *buf = xmlStrdup(xmlSchemaElemDesCT);
735 *buf = xmlStrcat(*buf, BAD_CAST " '");
736 *buf = xmlStrcat(*buf, item->name);
737 *buf = xmlStrcat(*buf, BAD_CAST "'");
738 } else {
739 *buf = xmlStrdup(xmlSchemaElemDesCT);
740 *buf = xmlStrcat(*buf, BAD_CAST " local");
741 }
742 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
743 xmlSchemaAttributePtr attr;
744
745 attr = (xmlSchemaAttributePtr) item;
746 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
747 (attr->ref == NULL)) {
748 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
749 *buf = xmlStrcat(*buf, BAD_CAST " '");
750 *buf = xmlStrcat(*buf, attr->name);
751 *buf = xmlStrcat(*buf, BAD_CAST "'");
752 } else {
753 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
754 *buf = xmlStrcat(*buf, BAD_CAST " '");
755 *buf = xmlStrcat(*buf, attr->refPrefix);
756 *buf = xmlStrcat(*buf, BAD_CAST ":");
757 *buf = xmlStrcat(*buf, attr->ref);
758 *buf = xmlStrcat(*buf, BAD_CAST "'");
759 }
760 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
761 xmlSchemaElementPtr elem;
762
763 elem = (xmlSchemaElementPtr) item;
764 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
765 (elem->ref == NULL)) {
766 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
767 *buf = xmlStrcat(*buf, BAD_CAST " '");
768 *buf = xmlStrcat(*buf, elem->name);
769 *buf = xmlStrcat(*buf, BAD_CAST "'");
770 } else {
771 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
772 *buf = xmlStrcat(*buf, BAD_CAST " '");
773 *buf = xmlStrcat(*buf, elem->refPrefix);
774 *buf = xmlStrcat(*buf, BAD_CAST ":");
775 *buf = xmlStrcat(*buf, elem->ref);
776 *buf = xmlStrcat(*buf, BAD_CAST "'");
777 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000778 } else
779 named = 0;
780 } else
781 named = 0;
782
783 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000784 xmlNodePtr elem;
785
786 if (itemNode->type == XML_ATTRIBUTE_NODE)
787 elem = itemNode->parent;
788 else
789 elem = itemNode;
790 *buf = xmlStrdup(BAD_CAST "Element '");
791 if (parsing)
792 *buf = xmlStrcat(*buf, elem->name);
793 else
794 *buf = xmlStrcat(*buf,
795 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
796 *buf = xmlStrcat(*buf, BAD_CAST "'");
797 }
798 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
799 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
800 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
801 itemNode->ns, itemNode->name));
802 *buf = xmlStrcat(*buf, BAD_CAST "'");
803 }
804 FREE_AND_NULL(str);
805
806 return (*buf);
807}
808
809/**
810 * xmlSchemaPFormatItemDes:
811 * @buf: the string buffer
812 * @item: the item as a schema object
813 * @itemNode: the item as a node
814 *
815 * If the pointer to @buf is not NULL and @but holds no value,
816 * the value is set to a item designation using
817 * xmlSchemaFormatItemForReport. This one avoids adding
818 * an attribute designation postfix.
819 *
820 * Returns a string of all enumeration elements.
821 */
822static void
823xmlSchemaPRequestItemDes(xmlChar **buf,
824 xmlSchemaTypePtr item,
825 xmlNodePtr itemNode)
826{
827 if ((buf == 0) || (*buf != NULL))
828 return;
829 if (itemNode->type == XML_ATTRIBUTE_NODE)
830 itemNode = itemNode->parent;
831 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
832}
833
834/**
835 * xmlSchemaFormatFacetEnumSet:
836 * @buf: the string buffer
837 * @type: the type holding the enumeration facets
838 *
839 * Builds a string consisting of all enumeration elements.
840 *
841 * Returns a string of all enumeration elements.
842 */
843static const xmlChar *
844xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
845{
846 xmlSchemaFacetLinkPtr link;
847
848 if (*buf != NULL)
849 xmlFree(*buf);
850 *buf = NULL;
851 for (link = type->facetSet; link != NULL; link = link->next) {
852 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
853 if (*buf == NULL) {
854 *buf = xmlStrdup(BAD_CAST "'");
855 *buf = xmlStrcat(*buf, link->facet->value);
856 *buf = xmlStrcat(*buf, BAD_CAST "'");
857 } else {
858 *buf = xmlStrcat(*buf, BAD_CAST ", '");
859 *buf = xmlStrcat(*buf, link->facet->value);
860 *buf = xmlStrcat(*buf, BAD_CAST "'");
861 }
862 }
863 }
864 return ((const xmlChar *) *buf);
865}
866
867/**
868 * xmlSchemaVFacetErr:
869 * @ctxt: the schema validation context
870 * @error: the error code
871 * @node: the node to be validated
872 * @value: the value of the node
873 * @type: the type holding the facet
874 * @facet: the facet
875 * @message: the error message of NULL
876 * @str1: extra data
877 * @str2: extra data
878 * @str3: extra data
879 *
880 * Reports a facet validation error.
881 * TODO: Should this report the value of an element as well?
882 */
883static void
884xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
885 xmlParserErrors error,
886 xmlNodePtr node,
887 const xmlChar *value,
888 unsigned long length,
889 xmlSchemaTypePtr type,
890 xmlSchemaFacetPtr facet,
891 const char *message,
892 const xmlChar *str1,
893 const xmlChar *str2,
894 const xmlChar *str3)
895{
896 xmlChar *str = NULL, *msg = NULL;
897 xmlSchemaTypeType facetType;
898
899 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
900 msg = xmlStrcat(msg, BAD_CAST " [");
901 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
902 msg = xmlStrcat(msg, BAD_CAST ", facet '");
903 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
904 facetType = XML_SCHEMA_FACET_ENUMERATION;
905 /*
906 * If enumerations are validated, one must not expect the
907 * facet to be given.
908 */
909 } else
910 facetType = facet->type;
911 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
912 msg = xmlStrcat(msg, BAD_CAST "']: ");
913 if (message == NULL) {
914 /*
915 * Use a default message.
916 */
917 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
918 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
919 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
920
921 char len[25], actLen[25];
922
923 /* FIXME, TODO: What is the max expected string length of the
924 * this value?
925 */
926 if (node->type == XML_ATTRIBUTE_NODE)
927 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
928 else
929 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
930
931 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
932 snprintf(actLen, 24, "%lu", length);
933
934 if (facetType == XML_SCHEMA_FACET_LENGTH)
935 msg = xmlStrcat(msg,
936 BAD_CAST "this differs from the allowed length of '%s'.\n");
937 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
938 msg = xmlStrcat(msg,
939 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
940 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
941 msg = xmlStrcat(msg,
942 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
943
944 if (node->type == XML_ATTRIBUTE_NODE)
945 xmlSchemaVErrExt(ctxt, node, error,
946 (const char *) msg,
947 value, (const xmlChar *) actLen, (const xmlChar *) len,
948 NULL, NULL);
949 else
950 xmlSchemaVErr(ctxt, node, error,
951 (const char *) msg,
952 (const xmlChar *) actLen, (const xmlChar *) len);
953
954 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
955 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
956 "of the set {%s}.\n");
957 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
958 xmlSchemaFormatFacetEnumSet(&str, type));
959 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
960 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
961 "by the pattern '%s'.\n");
962 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
963 facet->value);
964 } else if (node->type == XML_ATTRIBUTE_NODE) {
965 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
966 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
967 } else {
968 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
969 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
970 }
971 } else {
972 msg = xmlStrcat(msg, (const xmlChar *) message);
973 msg = xmlStrcat(msg, BAD_CAST ".\n");
974 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
975 }
976 FREE_AND_NULL(str)
977 xmlFree(msg);
978}
979
980/**
981 * xmlSchemaVSimpleTypeErr:
982 * @ctxt: the schema validation context
983 * @error: the error code
984 * @type: the type used for validation
985 * @node: the node containing the validated value
986 * @value: the validated value
987 *
988 * Reports a simple type validation error.
989 * TODO: Should this report the value of an element as well?
990 */
991static void
992xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
993 xmlParserErrors error,
994 xmlNodePtr node,
995 const xmlChar *value,
996 xmlSchemaTypePtr type)
997{
998 xmlChar *str = NULL, *msg = NULL;
999
1000 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1001 msg = xmlStrcat(msg, BAD_CAST " [");
1002 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1003 if (node->type == XML_ATTRIBUTE_NODE) {
1004 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1005 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1006 } else {
1007 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1008 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1009 }
1010 FREE_AND_NULL(str)
1011 xmlFree(msg);
1012}
1013
1014/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001015 * xmlSchemaVComplexTypeErr:
1016 * @ctxt: the schema validation context
1017 * @error: the error code
1018 * @node: the node containing the validated value
1019 * @type: the complex type used for validation
1020 * @message: the error message
1021 *
1022 * Reports a complex type validation error.
1023 */
1024static void
1025xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1026 xmlParserErrors error,
1027 xmlNodePtr node,
1028 xmlSchemaTypePtr type,
1029 const char *message)
1030{
1031 xmlChar *str = NULL, *msg = NULL;
1032
1033 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1034 msg = xmlStrcat(msg, BAD_CAST " [");
1035 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1036 msg = xmlStrcat(msg, BAD_CAST "]: %s.\n");
1037 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1038 (const xmlChar *) message, NULL);
1039 FREE_AND_NULL(str)
1040 xmlFree(msg);
1041}
1042
1043/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001044 * xmlSchemaPMissingAttrErr:
1045 * @ctxt: the schema validation context
1046 * @ownerDes: the designation of the owner
1047 * @ownerName: the name of the owner
1048 * @ownerItem: the owner as a schema object
1049 * @ownerElem: the owner as an element node
1050 * @node: the parent element node of the missing attribute node
1051 * @type: the corresponding type of the attribute node
1052 *
1053 * Reports an illegal attribute.
1054 */
1055static void
1056xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1057 xmlParserErrors error,
1058 xmlChar **ownerDes,
1059 xmlSchemaTypePtr ownerItem,
1060 xmlNodePtr ownerElem,
1061 const char *name,
1062 const char *message)
1063{
1064 xmlChar *des = NULL;
1065
1066 if (ownerDes == NULL)
1067 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1068 else if (*ownerDes == NULL) {
1069 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1070 des = *ownerDes;
1071 } else
1072 des = *ownerDes;
1073 if (message != NULL)
1074 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1075 else
1076 xmlSchemaPErr(ctxt, ownerElem, error,
1077 "%s: The attribute '%s' is required but missing.\n",
1078 BAD_CAST des, BAD_CAST name);
1079 if (ownerDes == NULL)
1080 FREE_AND_NULL(des);
1081}
1082
William M. Brack2f2a6632004-08-20 23:09:47 +00001083/**
1084 * xmlSchemaCompTypeToString:
1085 * @type: the type of the schema item
1086 *
1087 * Returns the component name of a schema item.
1088 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001089static const char *
1090xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1091{
1092 switch (type) {
1093 case XML_SCHEMA_TYPE_SIMPLE:
1094 return("simple type definition");
1095 case XML_SCHEMA_TYPE_COMPLEX:
1096 return("complex type definition");
1097 case XML_SCHEMA_TYPE_ELEMENT:
1098 return("element declaration");
1099 case XML_SCHEMA_TYPE_ATTRIBUTE:
1100 return("attribute declaration");
1101 case XML_SCHEMA_TYPE_GROUP:
1102 return("model group definition");
1103 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1104 return("attribute group definition");
1105 case XML_SCHEMA_TYPE_NOTATION:
1106 return("notation declaration");
1107 default:
1108 return("Not a schema component");
1109 }
1110}
1111/**
1112 * xmlSchemaPResCompAttrErr:
1113 * @ctxt: the schema validation context
1114 * @error: the error code
1115 * @ownerDes: the designation of the owner
1116 * @ownerItem: the owner as a schema object
1117 * @ownerElem: the owner as an element node
1118 * @name: the name of the attribute holding the QName
1119 * @refName: the referenced local name
1120 * @refURI: the referenced namespace URI
1121 * @message: optional message
1122 *
1123 * Used to report QName attribute values that failed to resolve
1124 * to schema components.
1125 */
1126static void
1127xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1128 xmlParserErrors error,
1129 xmlChar **ownerDes,
1130 xmlSchemaTypePtr ownerItem,
1131 xmlNodePtr ownerElem,
1132 const char *name,
1133 const xmlChar *refName,
1134 const xmlChar *refURI,
1135 xmlSchemaTypeType refType,
1136 const char *refTypeStr)
1137{
1138 xmlChar *des = NULL, *strA = NULL;
1139
1140 if (ownerDes == NULL)
1141 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1142 else if (*ownerDes == NULL) {
1143 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1144 des = *ownerDes;
1145 } else
1146 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001147 if (refTypeStr == NULL)
1148 refTypeStr = xmlSchemaCompTypeToString(refType);
1149 xmlSchemaPErrExt(ctxt, ownerElem, error,
1150 NULL, NULL, NULL,
1151 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1152 "%s.\n", BAD_CAST des, BAD_CAST name,
1153 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1154 BAD_CAST refTypeStr, NULL);
1155 if (ownerDes == NULL)
1156 FREE_AND_NULL(des)
1157 FREE_AND_NULL(strA)
1158}
1159
William M. Brack2f2a6632004-08-20 23:09:47 +00001160/**
1161 * xmlSchemaPCustomAttrErr:
1162 * @ctxt: the schema parser context
1163 * @error: the error code
1164 * @ownerDes: the designation of the owner
1165 * @ownerItem: the owner as a schema object
1166 * @attr: the illegal attribute node
1167 *
1168 * Reports an illegal attribute during the parse.
1169 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001170static void
1171xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001172 xmlParserErrors error,
1173 xmlChar **ownerDes,
1174 xmlSchemaTypePtr ownerItem,
1175 xmlAttrPtr attr,
1176 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001177{
1178 xmlChar *des = NULL;
1179
1180 if (ownerDes == NULL)
1181 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1182 else if (*ownerDes == NULL) {
1183 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1184 des = *ownerDes;
1185 } else
1186 des = *ownerDes;
1187 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1188 "%s, attribute '%s': %s.\n",
1189 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1190 if (ownerDes == NULL)
1191 FREE_AND_NULL(des);
1192}
1193
1194/**
1195 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001196 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001197 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001198 * @ownerDes: the designation of the attribute's owner
1199 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001200 * @attr: the illegal attribute node
1201 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001202 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001203 */
1204static void
1205xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1206 xmlParserErrors error,
1207 xmlChar **ownerDes,
1208 xmlSchemaTypePtr ownerItem,
1209 xmlAttrPtr attr)
1210{
1211 xmlChar *des = NULL, *strA = NULL;
1212
1213 if (ownerDes == NULL)
1214 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1215 else if (*ownerDes == NULL) {
1216 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1217 des = *ownerDes;
1218 } else
1219 des = *ownerDes;
1220 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1221 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1222 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1223 if (ownerDes == NULL)
1224 FREE_AND_NULL(des);
1225 FREE_AND_NULL(strA);
1226}
1227
William M. Brack2f2a6632004-08-20 23:09:47 +00001228/**
1229 * xmlSchemaPAquireDes:
1230 * @des: the first designation
1231 * @itemDes: the second designation
1232 * @item: the schema item
1233 * @itemElem: the node of the schema item
1234 *
1235 * Creates a designation for an item.
1236 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001237static void
1238xmlSchemaPAquireDes(xmlChar **des,
1239 xmlChar **itemDes,
1240 xmlSchemaTypePtr item,
1241 xmlNodePtr itemElem)
1242{
1243 if (itemDes == NULL)
1244 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1245 else if (*itemDes == NULL) {
1246 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1247 *des = *itemDes;
1248 } else
1249 *des = *itemDes;
1250}
1251
William M. Brack2f2a6632004-08-20 23:09:47 +00001252/**
1253 * xmlSchemaPCustomErr:
1254 * @ctxt: the schema parser context
1255 * @error: the error code
1256 * @itemDes: the designation of the schema item
1257 * @item: the schema item
1258 * @itemElem: the node of the schema item
1259 * @message: the error message
1260 * @str1: an optional param for the error message
1261 * @str2: an optional param for the error message
1262 * @str3: an optional param for the error message
1263 *
1264 * Reports an error during parsing.
1265 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001266static void
1267xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1268 xmlParserErrors error,
1269 xmlChar **itemDes,
1270 xmlSchemaTypePtr item,
1271 xmlNodePtr itemElem,
1272 const char *message,
1273 const xmlChar *str1,
1274 const xmlChar *str2,
1275 const xmlChar *str3)
1276{
1277 xmlChar *des = NULL, *msg = NULL;
1278
1279 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1280 msg = xmlStrdup(BAD_CAST "%s: ");
1281 msg = xmlStrcat(msg, (const xmlChar *) message);
1282 msg = xmlStrcat(msg, BAD_CAST ".\n");
1283 if ((itemElem == NULL) && (item != NULL))
1284 itemElem = item->node;
1285 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1286 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1287 if (itemDes == NULL)
1288 FREE_AND_NULL(des);
1289 FREE_AND_NULL(msg);
1290}
1291
William M. Brack2f2a6632004-08-20 23:09:47 +00001292/**
1293 * xmlSchemaPCustomErr:
1294 * @ctxt: the schema parser context
1295 * @error: the error code
1296 * @itemDes: the designation of the schema item
1297 * @item: the schema item
1298 * @itemElem: the node of the schema item
1299 * @message: the error message
1300 * @str1: the optional param for the error message
1301 *
1302 * Reports an error during parsing.
1303 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001304static void
1305xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1306 xmlParserErrors error,
1307 xmlChar **itemDes,
1308 xmlSchemaTypePtr item,
1309 xmlNodePtr itemElem,
1310 const char *message,
1311 const xmlChar *str1)
1312{
1313 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1314 str1, NULL, NULL);
1315}
1316
William M. Brack2f2a6632004-08-20 23:09:47 +00001317/**
1318 * xmlSchemaPAttrUseErr:
1319 * @ctxt: the schema parser context
1320 * @error: the error code
1321 * @itemDes: the designation of the schema type
1322 * @item: the schema type
1323 * @itemElem: the node of the schema type
1324 * @attr: the invalid schema attribute
1325 * @message: the error message
1326 * @str1: the optional param for the error message
1327 *
1328 * Reports an attribute use error during parsing.
1329 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001330static void
1331xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1332 xmlParserErrors error,
1333 xmlChar **itemDes,
1334 xmlSchemaTypePtr item,
1335 xmlNodePtr itemElem,
1336 const xmlSchemaAttributePtr attr,
1337 const char *message,
1338 const xmlChar *str1)
1339{
1340 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1341
1342 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1343 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1344 xmlSchemaGetAttrName(attr));
1345 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1346 msg = xmlStrcat(msg, (const xmlChar *) message);
1347 msg = xmlStrcat(msg, BAD_CAST ".\n");
1348 if ((itemElem == NULL) && (item != NULL))
1349 itemElem = item->node;
1350 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1351 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1352 if (itemDes == NULL)
1353 FREE_AND_NULL(des);
1354 FREE_AND_NULL(strA);
1355 xmlFree(msg);
1356}
1357
William M. Brack2f2a6632004-08-20 23:09:47 +00001358/**
1359 * xmlSchemaPIllegalFacetAtomicErr:
1360 * @ctxt: the schema parser context
1361 * @error: the error code
1362 * @itemDes: the designation of the type
1363 * @item: the schema type
1364 * @baseItem: the base type of type
1365 * @facet: the illegal facet
1366 *
1367 * Reports an illegal facet for atomic simple types.
1368 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001369static void
1370xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1371 xmlParserErrors error,
1372 xmlChar **itemDes,
1373 xmlSchemaTypePtr item,
1374 xmlSchemaTypePtr baseItem,
1375 xmlSchemaFacetPtr facet)
1376{
1377 xmlChar *des = NULL, *strT = NULL;
1378
1379 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1380 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1381 "%s: The facet '%s' is not allowed on types derived from the "
1382 "type %s.\n",
1383 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1384 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1385 NULL, NULL);
1386 if (itemDes == NULL)
1387 FREE_AND_NULL(des);
1388 FREE_AND_NULL(strT);
1389}
1390
William M. Brack2f2a6632004-08-20 23:09:47 +00001391/**
1392 * xmlSchemaPIllegalFacetListUnionErr:
1393 * @ctxt: the schema parser context
1394 * @error: the error code
1395 * @itemDes: the designation of the schema item involved
1396 * @item: the schema item involved
1397 * @facet: the illegal facet
1398 *
1399 * Reports an illegal facet for <list> and <union>.
1400 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001401static void
1402xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1403 xmlParserErrors error,
1404 xmlChar **itemDes,
1405 xmlSchemaTypePtr item,
1406 xmlSchemaFacetPtr facet)
1407{
1408 xmlChar *des = NULL, *strT = NULL;
1409
1410 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1411 xmlSchemaPErr(ctxt, item->node, error,
1412 "%s: The facet '%s' is not allowed.\n",
1413 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1414 if (itemDes == NULL)
1415 FREE_AND_NULL(des);
1416 FREE_AND_NULL(strT);
1417}
1418
1419/**
1420 * xmlSchemaPMutualExclAttrErr:
1421 * @ctxt: the schema validation context
1422 * @error: the error code
1423 * @elemDes: the designation of the parent element node
1424 * @attr: the bad attribute node
1425 * @type: the corresponding type of the attribute node
1426 *
1427 * Reports an illegal attribute.
1428 */
1429static void
1430xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1431 xmlParserErrors error,
1432 xmlChar **ownerDes,
1433 xmlSchemaTypePtr ownerItem,
1434 xmlAttrPtr attr,
1435 const char *name1,
1436 const char *name2)
1437{
1438 xmlChar *des = NULL;
1439
1440 if (ownerDes == NULL)
1441 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1442 else if (*ownerDes == NULL) {
1443 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1444 des = *ownerDes;
1445 } else
1446 des = *ownerDes;
1447 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1448 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1449 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1450 if (ownerDes == NULL)
1451 FREE_AND_NULL(des)
1452}
1453
1454/**
1455 * xmlSchemaPSimpleTypeErr:
1456 * @ctxt: the schema validation context
1457 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001458 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001459 * @ownerDes: the designation of the owner
1460 * @ownerItem: the schema object if existent
1461 * @node: the validated node
1462 * @value: the validated value
1463 *
1464 * Reports a simple type validation error.
1465 * TODO: Should this report the value of an element as well?
1466 */
1467static void
1468xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1469 xmlParserErrors error,
1470 xmlChar **ownerDes,
1471 xmlSchemaTypePtr ownerItem,
1472 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001473 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001474 const char *typeDes,
1475 const xmlChar *value,
1476 const char *message,
1477 const xmlChar *str1,
1478 const xmlChar *str2)
1479{
William M. Brack2f2a6632004-08-20 23:09:47 +00001480 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001481
1482 if (ownerDes == NULL)
1483 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1484 else if (*ownerDes == NULL) {
1485 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1486 des = *ownerDes;
1487 } else
1488 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001489 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001490 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001491 if (message == NULL) {
1492 /*
1493 * Use default messages.
1494 */
1495 if (node->type == XML_ATTRIBUTE_NODE) {
1496 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1497 "%s, attribute '%s' [%s]: The value '%s' is not "
1498 "valid.\n",
1499 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1500 node->name), BAD_CAST typeDes, value, NULL);
1501 } else {
1502 xmlSchemaPErr(ctxt, node, error,
1503 "%s [%s]: The character content is not valid.\n",
1504 BAD_CAST des, BAD_CAST typeDes);
1505 }
1506 } else {
1507 xmlChar *msg;
1508
1509 msg = xmlStrdup(BAD_CAST "%s");
1510 if (node->type == XML_ATTRIBUTE_NODE)
1511 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1512 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1513 msg = xmlStrcat(msg, (const xmlChar *) message);
1514 msg = xmlStrcat(msg, BAD_CAST ".\n");
1515 if (node->type == XML_ATTRIBUTE_NODE) {
1516 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1517 (const char *) msg,
1518 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1519 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1520 } else {
1521 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1522 (const char *) msg,
1523 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1524 }
1525 xmlFree(msg);
1526 }
1527 /* Cleanup. */
1528 FREE_AND_NULL(strA)
1529 FREE_AND_NULL(strT)
1530 if (ownerDes == NULL)
1531 FREE_AND_NULL(des)
1532}
1533
William M. Brack2f2a6632004-08-20 23:09:47 +00001534/**
1535 * xmlSchemaPContentErr:
1536 * @ctxt: the schema parser context
1537 * @error: the error code
1538 * @onwerDes: the designation of the holder of the content
1539 * @ownerItem: the owner item of the holder of the content
1540 * @ownerElem: the node of the holder of the content
1541 * @child: the invalid child node
1542 * @message: the optional error message
1543 * @content: the optional string describing the correct content
1544 *
1545 * Reports an error concerning the content of a schema element.
1546 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001547static void
1548xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1549 xmlParserErrors error,
1550 xmlChar **ownerDes,
1551 xmlSchemaTypePtr ownerItem,
1552 xmlNodePtr ownerElem,
1553 xmlNodePtr child,
1554 const char *message,
1555 const char *content)
1556{
1557 xmlChar *des = NULL;
1558
1559 if (ownerDes == NULL)
1560 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1561 else if (*ownerDes == NULL) {
1562 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1563 des = *ownerDes;
1564 } else
1565 des = *ownerDes;
1566 if (message != NULL)
1567 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1568 "%s: %s.\n",
1569 BAD_CAST des, BAD_CAST message);
1570 else {
1571 if (content != NULL) {
1572 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1573 "%s: The content is not valid. Expected is %s.\n",
1574 BAD_CAST des, BAD_CAST content);
1575 } else {
1576 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1577 "%s: The content is not valid.\n",
1578 BAD_CAST des, NULL);
1579 }
1580 }
1581 if (ownerDes == NULL)
1582 FREE_AND_NULL(des)
1583}
1584
1585/**
1586 * xmlSchemaVIllegalAttrErr:
1587 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001588 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001589 * @attr: the illegal attribute node
1590 *
1591 * Reports an illegal attribute.
1592 */
1593static void
1594xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001595 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001596 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001597{
1598 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001599
1600 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1601 error,
1602 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001603 "%s: The attribute '%s' is not allowed.\n",
1604 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1605 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1606 FREE_AND_NULL(strE)
1607 FREE_AND_NULL(strA)
1608}
1609
William M. Brack2f2a6632004-08-20 23:09:47 +00001610/**
1611 * xmlSchemaVCustomErr:
1612 * @ctxt: the schema validation context
1613 * @error: the error code
1614 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001615 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001616 * @message: the error message
1617 * @str1: the optional param for the message
1618 *
1619 * Reports a validation error.
1620 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001621static void
1622xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1623 xmlParserErrors error,
1624 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001625 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001626 const char *message,
1627 const xmlChar *str1)
1628{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001629 xmlChar *msg = NULL, *str = NULL;
1630
1631 if (node == NULL) {
1632 xmlSchemaVErr(ctxt, NULL,
1633 XML_SCHEMAV_INTERNAL,
1634 "Internal error: xmlSchemaVCustomErr, no node "
1635 "given.\n", NULL, NULL);
1636 return;
1637 }
1638 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1639 if (node->type != XML_DOCUMENT_NODE) {
1640 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1641 if (type != NULL) {
1642 msg = xmlStrcat(msg, BAD_CAST " [");
1643 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1644 msg = xmlStrcat(msg, BAD_CAST "]");
1645 }
1646 msg = xmlStrcat(msg, BAD_CAST ": ");
1647 } else
1648 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001649 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001650 msg = xmlStrcat(msg, BAD_CAST ".\n");
1651 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1652 FREE_AND_NULL(msg)
1653 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654}
1655
William M. Brack2f2a6632004-08-20 23:09:47 +00001656/**
1657 * xmlSchemaWildcardPCToString:
1658 * @pc: the type of processContents
1659 *
1660 * Returns a string representation of the type of
1661 * processContents.
1662 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001663static const char *
1664xmlSchemaWildcardPCToString(int pc)
1665{
1666 switch (pc) {
1667 case XML_SCHEMAS_ANY_SKIP:
1668 return ("skip");
1669 case XML_SCHEMAS_ANY_LAX:
1670 return ("lax");
1671 case XML_SCHEMAS_ANY_STRICT:
1672 return ("strict");
1673 default:
1674 return ("invalid process contents");
1675 }
1676}
1677
William M. Brack2f2a6632004-08-20 23:09:47 +00001678/**
1679 * xmlSchemaVWildcardErr:
1680 * @ctxt: the schema validation context
1681 * @error: the error code
1682 * @node: the validated node
1683 * @wild: the wildcard used
1684 * @message: the error message
1685 *
1686 * Reports an validation-by-wildcard error.
1687 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001688static void
1689xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1690 xmlParserErrors error,
1691 xmlNodePtr node,
1692 xmlSchemaWildcardPtr wild,
1693 const char *message)
1694{
1695 xmlChar *des = NULL, *msg = NULL;
1696
1697 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1698 msg = xmlStrdup(BAD_CAST "%s, [");
1699 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1700 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1701 msg = xmlStrcat(msg, (const xmlChar *) message);
1702 msg = xmlStrcat(msg, BAD_CAST ".\n");
1703 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1704 FREE_AND_NULL(des);
1705 FREE_AND_NULL(msg);
1706}
1707
1708/**
1709 * xmlSchemaVMissingAttrErr:
1710 * @ctxt: the schema validation context
1711 * @node: the parent element node of the missing attribute node
1712 * @type: the corresponding type of the attribute node
1713 *
1714 * Reports an illegal attribute.
1715 */
1716static void
1717xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1718 xmlNodePtr elem,
1719 xmlSchemaAttributePtr type)
1720{
1721 const xmlChar *name, *uri;
1722 xmlChar *strE = NULL, *strA = NULL;
1723
1724 if (type->ref != NULL) {
1725 name = type->ref;
1726 uri = type->refNs;
1727 } else {
1728 name = type->name;
1729 uri = type->targetNamespace;
1730 }
1731 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001732 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1733 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001734 "%s: The attribute %s is required but missing.\n",
1735 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1736 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1737 FREE_AND_NULL(strE)
1738 FREE_AND_NULL(strA)
1739}
1740
Daniel Veillard4255d502002-04-16 15:50:10 +00001741/************************************************************************
1742 * *
1743 * Allocation functions *
1744 * *
1745 ************************************************************************/
1746
1747/**
1748 * xmlSchemaNewSchema:
William M. Brack08171912003-12-29 02:52:11 +00001749 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001750 *
1751 * Allocate a new Schema structure.
1752 *
1753 * Returns the newly allocated structure or NULL in case or error
1754 */
1755static xmlSchemaPtr
1756xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1757{
1758 xmlSchemaPtr ret;
1759
1760 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1761 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001762 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001763 return (NULL);
1764 }
1765 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001766 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001767 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001768
1769 return (ret);
1770}
1771
1772/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001773 * xmlSchemaNewSchema:
1774 * @ctxt: a schema validation context
1775 *
1776 * Allocate a new Schema structure.
1777 *
1778 * Returns the newly allocated structure or NULL in case or error
1779 */
1780static xmlSchemaAssemblePtr
1781xmlSchemaNewAssemble(void)
1782{
1783 xmlSchemaAssemblePtr ret;
1784
1785 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1786 if (ret == NULL) {
1787 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1788 return (NULL);
1789 }
1790 memset(ret, 0, sizeof(xmlSchemaAssemble));
1791 ret->items = NULL;
1792 return (ret);
1793}
1794
1795/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001796 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001797 *
1798 * Allocate a new Facet structure.
1799 *
1800 * Returns the newly allocated structure or NULL in case or error
1801 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001802xmlSchemaFacetPtr
1803xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001804{
1805 xmlSchemaFacetPtr ret;
1806
1807 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1808 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001809 return (NULL);
1810 }
1811 memset(ret, 0, sizeof(xmlSchemaFacet));
1812
1813 return (ret);
1814}
1815
1816/**
1817 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001818 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001819 * @node: a node
1820 *
1821 * Allocate a new annotation structure.
1822 *
1823 * Returns the newly allocated structure or NULL in case or error
1824 */
1825static xmlSchemaAnnotPtr
1826xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1827{
1828 xmlSchemaAnnotPtr ret;
1829
1830 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1831 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001832 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001833 return (NULL);
1834 }
1835 memset(ret, 0, sizeof(xmlSchemaAnnot));
1836 ret->content = node;
1837 return (ret);
1838}
1839
1840/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001841 * xmlSchemaFreeAnnot:
1842 * @annot: a schema type structure
1843 *
1844 * Deallocate a annotation structure
1845 */
1846static void
1847xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1848{
1849 if (annot == NULL)
1850 return;
1851 xmlFree(annot);
1852}
1853
1854/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001855 * xmlSchemaFreeImport:
1856 * @import: a schema import structure
1857 *
1858 * Deallocate an import structure
1859 */
1860static void
1861xmlSchemaFreeImport(xmlSchemaImportPtr import)
1862{
1863 if (import == NULL)
1864 return;
1865
1866 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001867 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001868 xmlFree(import);
1869}
1870
1871/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001872 * xmlSchemaFreeInclude:
1873 * @include: a schema include structure
1874 *
1875 * Deallocate an include structure
1876 */
1877static void
1878xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1879{
1880 if (include == NULL)
1881 return;
1882
1883 xmlFreeDoc(include->doc);
1884 xmlFree(include);
1885}
1886
1887/**
1888 * xmlSchemaFreeIncludeList:
1889 * @includes: a schema include list
1890 *
1891 * Deallocate an include structure
1892 */
1893static void
1894xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1895{
1896 xmlSchemaIncludePtr next;
1897
1898 while (includes != NULL) {
1899 next = includes->next;
1900 xmlSchemaFreeInclude(includes);
1901 includes = next;
1902 }
1903}
1904
1905/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001906 * xmlSchemaFreeNotation:
1907 * @schema: a schema notation structure
1908 *
1909 * Deallocate a Schema Notation structure.
1910 */
1911static void
1912xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1913{
1914 if (nota == NULL)
1915 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001916 xmlFree(nota);
1917}
1918
1919/**
1920 * xmlSchemaFreeAttribute:
1921 * @schema: a schema attribute structure
1922 *
1923 * Deallocate a Schema Attribute structure.
1924 */
1925static void
1926xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1927{
1928 if (attr == NULL)
1929 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001930 if (attr->annot != NULL)
1931 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00001932 xmlFree(attr);
1933}
1934
1935/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001936 * xmlSchemaFreeWildcardNsSet:
1937 * set: a schema wildcard namespace
1938 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001939 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001940 */
1941static void
1942xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1943{
1944 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001945
Daniel Veillard3646d642004-06-02 19:19:14 +00001946 while (set != NULL) {
1947 next = set->next;
1948 xmlFree(set);
1949 set = next;
1950 }
1951}
1952
1953/**
1954 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001955 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001956 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001957 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00001958 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00001959void
Daniel Veillard3646d642004-06-02 19:19:14 +00001960xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
1961{
1962 if (wildcard == NULL)
1963 return;
1964 if (wildcard->annot != NULL)
1965 xmlSchemaFreeAnnot(wildcard->annot);
1966 if (wildcard->nsSet != NULL)
1967 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
1968 if (wildcard->negNsSet != NULL)
1969 xmlFree(wildcard->negNsSet);
1970 xmlFree(wildcard);
1971}
1972
1973/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001974 * xmlSchemaFreeAttributeGroup:
1975 * @schema: a schema attribute group structure
1976 *
1977 * Deallocate a Schema Attribute Group structure.
1978 */
1979static void
1980xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
1981{
1982 if (attr == NULL)
1983 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00001984 if (attr->annot != NULL)
1985 xmlSchemaFreeAnnot(attr->annot);
1986 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
1987 (attr->attributeWildcard != NULL))
1988 xmlSchemaFreeWildcard(attr->attributeWildcard);
1989
Daniel Veillard4255d502002-04-16 15:50:10 +00001990 xmlFree(attr);
1991}
1992
1993/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001994 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001995 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00001996 *
1997 * Deallocate a list of schema attribute uses.
1998 */
1999static void
2000xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2001{
2002 xmlSchemaAttributeLinkPtr next;
2003
2004 while (attrUse != NULL) {
2005 next = attrUse->next;
2006 xmlFree(attrUse);
2007 attrUse = next;
2008 }
2009}
2010
2011/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002012 * xmlSchemaFreeTypeLinkList:
2013 * @alink: a type link
2014 *
2015 * Deallocate a list of types.
2016 */
2017static void
2018xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2019{
2020 xmlSchemaTypeLinkPtr next;
2021
2022 while (link != NULL) {
2023 next = link->next;
2024 xmlFree(link);
2025 link = next;
2026 }
2027}
2028
2029/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002030 * xmlSchemaFreeElement:
2031 * @schema: a schema element structure
2032 *
2033 * Deallocate a Schema Element structure.
2034 */
2035static void
2036xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2037{
2038 if (elem == NULL)
2039 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002040 if (elem->annot != NULL)
2041 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002042 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002043 xmlRegFreeRegexp(elem->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002044 xmlFree(elem);
2045}
2046
2047/**
2048 * xmlSchemaFreeFacet:
2049 * @facet: a schema facet structure
2050 *
2051 * Deallocate a Schema Facet structure.
2052 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002053void
Daniel Veillard4255d502002-04-16 15:50:10 +00002054xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2055{
2056 if (facet == NULL)
2057 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002058 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002059 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002060 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002061 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002062 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002063 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002064 xmlFree(facet);
2065}
2066
2067/**
2068 * xmlSchemaFreeType:
2069 * @type: a schema type structure
2070 *
2071 * Deallocate a Schema Type structure.
2072 */
2073void
2074xmlSchemaFreeType(xmlSchemaTypePtr type)
2075{
2076 if (type == NULL)
2077 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002078 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002079 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002080 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002081 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002082
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002083 facet = type->facets;
2084 while (facet != NULL) {
2085 next = facet->next;
2086 xmlSchemaFreeFacet(facet);
2087 facet = next;
2088 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002089 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002090 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2091 if (type->attributeUses != NULL)
2092 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002093 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002094 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002095 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2096 /*
2097 * NOTE: The only case where an attribute wildcard
2098 * is not owned, is if a complex type inherits it
2099 * from a base type.
2100 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002101 xmlSchemaFreeWildcard(type->attributeWildcard);
2102 }
2103 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002104 if (type->memberTypes != NULL)
2105 xmlSchemaFreeTypeLinkList(type->memberTypes);
2106 if (type->facetSet != NULL) {
2107 xmlSchemaFacetLinkPtr next, link;
2108
2109 link = type->facetSet;
2110 do {
2111 next = link->next;
2112 xmlFree(link);
2113 link = next;
2114 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002115 }
2116 if (type->contModel != NULL)
2117 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002118 xmlFree(type);
2119}
2120
2121/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002122 * xmlSchemaFreeTypeList:
2123 * @type: a schema type structure
2124 *
2125 * Deallocate a Schema Type structure.
2126 */
2127static void
2128xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2129{
2130 xmlSchemaTypePtr next;
2131
2132 while (type != NULL) {
2133 next = type->redef;
2134 xmlSchemaFreeType(type);
2135 type = next;
2136 }
2137}
2138
2139/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002140 * xmlSchemaFree:
2141 * @schema: a schema structure
2142 *
2143 * Deallocate a Schema structure.
2144 */
2145void
2146xmlSchemaFree(xmlSchemaPtr schema)
2147{
2148 if (schema == NULL)
2149 return;
2150
Daniel Veillard4255d502002-04-16 15:50:10 +00002151 if (schema->notaDecl != NULL)
2152 xmlHashFree(schema->notaDecl,
2153 (xmlHashDeallocator) xmlSchemaFreeNotation);
2154 if (schema->attrDecl != NULL)
2155 xmlHashFree(schema->attrDecl,
2156 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2157 if (schema->attrgrpDecl != NULL)
2158 xmlHashFree(schema->attrgrpDecl,
2159 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2160 if (schema->elemDecl != NULL)
2161 xmlHashFree(schema->elemDecl,
2162 (xmlHashDeallocator) xmlSchemaFreeElement);
2163 if (schema->typeDecl != NULL)
2164 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002165 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002166 if (schema->groupDecl != NULL)
2167 xmlHashFree(schema->groupDecl,
2168 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002169 if (schema->schemasImports != NULL)
2170 xmlHashFree(schema->schemasImports,
2171 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002172 if (schema->includes != NULL) {
2173 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2174 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002175 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002176 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002177 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002178 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002179 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002180 xmlFree(schema);
2181}
2182
2183/************************************************************************
2184 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002185 * Debug functions *
2186 * *
2187 ************************************************************************/
2188
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002189#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002190
Daniel Veillard4255d502002-04-16 15:50:10 +00002191/**
2192 * xmlSchemaElementDump:
2193 * @elem: an element
2194 * @output: the file output
2195 *
2196 * Dump the element
2197 */
2198static void
2199xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002200 const xmlChar * name ATTRIBUTE_UNUSED,
2201 const xmlChar * context ATTRIBUTE_UNUSED,
2202 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002203{
2204 if (elem == NULL)
2205 return;
2206
2207 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002208 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2209 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002210 fprintf(output, ": %s ", elem->name);
2211 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002212 fprintf(output, "namespace '%s' ", namespace);
2213
Daniel Veillard4255d502002-04-16 15:50:10 +00002214 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002215 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002216 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002217 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002218 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002219 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002220 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002221 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002222 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002223 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002224 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002225 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002226 fprintf(output, "\n");
2227 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002228 fprintf(output, " ");
2229 if (elem->minOccurs != 1)
2230 fprintf(output, "min: %d ", elem->minOccurs);
2231 if (elem->maxOccurs >= UNBOUNDED)
2232 fprintf(output, "max: unbounded\n");
2233 else if (elem->maxOccurs != 1)
2234 fprintf(output, "max: %d\n", elem->maxOccurs);
2235 else
2236 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002237 }
2238 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002239 fprintf(output, " type: %s", elem->namedType);
2240 if (elem->namedTypeNs != NULL)
2241 fprintf(output, " ns %s\n", elem->namedTypeNs);
2242 else
2243 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002244 }
2245 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002246 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2247 if (elem->substGroupNs != NULL)
2248 fprintf(output, " ns %s\n", elem->substGroupNs);
2249 else
2250 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 }
2252 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002254}
2255
2256/**
2257 * xmlSchemaAnnotDump:
2258 * @output: the file output
2259 * @annot: a annotation
2260 *
2261 * Dump the annotation
2262 */
2263static void
2264xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2265{
2266 xmlChar *content;
2267
2268 if (annot == NULL)
2269 return;
2270
2271 content = xmlNodeGetContent(annot->content);
2272 if (content != NULL) {
2273 fprintf(output, " Annot: %s\n", content);
2274 xmlFree(content);
2275 } else
2276 fprintf(output, " Annot: empty\n");
2277}
2278
2279/**
2280 * xmlSchemaTypeDump:
2281 * @output: the file output
2282 * @type: a type structure
2283 *
2284 * Dump a SchemaType structure
2285 */
2286static void
2287xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2288{
2289 if (type == NULL) {
2290 fprintf(output, "Type: NULL\n");
2291 return;
2292 }
2293 fprintf(output, "Type: ");
2294 if (type->name != NULL)
2295 fprintf(output, "%s, ", type->name);
2296 else
2297 fprintf(output, "no name");
2298 switch (type->type) {
2299 case XML_SCHEMA_TYPE_BASIC:
2300 fprintf(output, "basic ");
2301 break;
2302 case XML_SCHEMA_TYPE_SIMPLE:
2303 fprintf(output, "simple ");
2304 break;
2305 case XML_SCHEMA_TYPE_COMPLEX:
2306 fprintf(output, "complex ");
2307 break;
2308 case XML_SCHEMA_TYPE_SEQUENCE:
2309 fprintf(output, "sequence ");
2310 break;
2311 case XML_SCHEMA_TYPE_CHOICE:
2312 fprintf(output, "choice ");
2313 break;
2314 case XML_SCHEMA_TYPE_ALL:
2315 fprintf(output, "all ");
2316 break;
2317 case XML_SCHEMA_TYPE_UR:
2318 fprintf(output, "ur ");
2319 break;
2320 case XML_SCHEMA_TYPE_RESTRICTION:
2321 fprintf(output, "restriction ");
2322 break;
2323 case XML_SCHEMA_TYPE_EXTENSION:
2324 fprintf(output, "extension ");
2325 break;
2326 default:
2327 fprintf(output, "unknowntype%d ", type->type);
2328 break;
2329 }
2330 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002331 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002332 }
2333 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002334 case XML_SCHEMA_CONTENT_UNKNOWN:
2335 fprintf(output, "unknown ");
2336 break;
2337 case XML_SCHEMA_CONTENT_EMPTY:
2338 fprintf(output, "empty ");
2339 break;
2340 case XML_SCHEMA_CONTENT_ELEMENTS:
2341 fprintf(output, "element ");
2342 break;
2343 case XML_SCHEMA_CONTENT_MIXED:
2344 fprintf(output, "mixed ");
2345 break;
2346 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002347 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002348 break;
2349 case XML_SCHEMA_CONTENT_BASIC:
2350 fprintf(output, "basic ");
2351 break;
2352 case XML_SCHEMA_CONTENT_SIMPLE:
2353 fprintf(output, "simple ");
2354 break;
2355 case XML_SCHEMA_CONTENT_ANY:
2356 fprintf(output, "any ");
2357 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002358 }
2359 fprintf(output, "\n");
2360 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002361 fprintf(output, " ");
2362 if (type->minOccurs != 1)
2363 fprintf(output, "min: %d ", type->minOccurs);
2364 if (type->maxOccurs >= UNBOUNDED)
2365 fprintf(output, "max: unbounded\n");
2366 else if (type->maxOccurs != 1)
2367 fprintf(output, "max: %d\n", type->maxOccurs);
2368 else
2369 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002370 }
2371 if (type->annot != NULL)
2372 xmlSchemaAnnotDump(output, type->annot);
2373 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002374 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002375
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002376 fprintf(output, " subtypes: ");
2377 while (sub != NULL) {
2378 fprintf(output, "%s ", sub->name);
2379 sub = sub->next;
2380 }
2381 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002382 }
2383
2384}
2385
2386/**
2387 * xmlSchemaDump:
2388 * @output: the file output
2389 * @schema: a schema structure
2390 *
2391 * Dump a Schema structure.
2392 */
2393void
2394xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2395{
2396 if (schema == NULL) {
2397 fprintf(output, "Schemas: NULL\n");
2398 return;
2399 }
2400 fprintf(output, "Schemas: ");
2401 if (schema->name != NULL)
2402 fprintf(output, "%s, ", schema->name);
2403 else
2404 fprintf(output, "no name, ");
2405 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002406 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002407 else
2408 fprintf(output, "no target namespace");
2409 fprintf(output, "\n");
2410 if (schema->annot != NULL)
2411 xmlSchemaAnnotDump(output, schema->annot);
2412
2413 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2414 output);
2415 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002416 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002417}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002418#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002419
2420/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002421 * *
2422 * Utilities *
2423 * *
2424 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002425
Daniel Veillardc0826a72004-08-10 14:17:33 +00002426/**
2427 * xmlSchemaGetPropNode:
2428 * @node: the element node
2429 * @name: the name of the attribute
2430 *
2431 * Seeks an attribute with a name of @name in
2432 * no namespace.
2433 *
2434 * Returns the attribute or NULL if not present.
2435 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002436static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002437xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002438{
2439 xmlAttrPtr prop;
2440
Daniel Veillardc0826a72004-08-10 14:17:33 +00002441 if ((node == NULL) || (name == NULL))
2442 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002443 prop = node->properties;
2444 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002445 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2446 return(prop);
2447 prop = prop->next;
2448 }
2449 return (NULL);
2450}
2451
2452/**
2453 * xmlSchemaGetPropNodeNs:
2454 * @node: the element node
2455 * @uri: the uri
2456 * @name: the name of the attribute
2457 *
2458 * Seeks an attribute with a local name of @name and
2459 * a namespace URI of @uri.
2460 *
2461 * Returns the attribute or NULL if not present.
2462 */
2463static xmlAttrPtr
2464xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2465{
2466 xmlAttrPtr prop;
2467
2468 if ((node == NULL) || (name == NULL))
2469 return(NULL);
2470 prop = node->properties;
2471 while (prop != NULL) {
2472 if ((prop->ns != NULL) &&
2473 xmlStrEqual(prop->name, BAD_CAST name) &&
2474 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002475 return(prop);
2476 prop = prop->next;
2477 }
2478 return (NULL);
2479}
2480
2481static const xmlChar *
2482xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2483{
2484 xmlChar *val;
2485 const xmlChar *ret;
2486
2487 val = xmlNodeGetContent(node);
2488 if (val == NULL)
2489 return(NULL);
2490 ret = xmlDictLookup(ctxt->dict, val, -1);
2491 xmlFree(val);
2492 return(ret);
2493}
2494
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002495/**
2496 * xmlSchemaGetProp:
2497 * @ctxt: the parser context
2498 * @node: the node
2499 * @name: the property name
2500 *
2501 * Read a attribute value and internalize the string
2502 *
2503 * Returns the string or NULL if not present.
2504 */
2505static const xmlChar *
2506xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2507 const char *name)
2508{
2509 xmlChar *val;
2510 const xmlChar *ret;
2511
2512 val = xmlGetProp(node, BAD_CAST name);
2513 if (val == NULL)
2514 return(NULL);
2515 ret = xmlDictLookup(ctxt->dict, val, -1);
2516 xmlFree(val);
2517 return(ret);
2518}
2519
William M. Brack29aa7722004-05-12 00:27:56 +00002520#if 0
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002521/**
2522 * xmlSchemaGetNamespace:
2523 * @ctxt: the parser context
2524 * @schema: the schemas containing the declaration
2525 * @node: the node
2526 * @qname: the QName to analyze
2527 *
2528 * Find the namespace name for the given declaration.
2529 *
2530 * Returns the local name for that declaration, as well as the namespace name
William M. Bracke7091952004-05-11 15:09:58 +00002531 * NOTE: This function is no longer used (Buchcik, May '04)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002532 */
2533static const xmlChar *
2534xmlSchemaGetNamespace(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
2535 xmlNodePtr node, const xmlChar *qname,
2536 const xmlChar **namespace) {
2537 int len;
2538 const xmlChar *name, *prefix, *def = NULL;
2539 xmlNsPtr ns;
2540
2541 *namespace = NULL;
2542
William M. Bracke7091952004-05-11 15:09:58 +00002543 /* TODO: The following seems to be not correct here:
2544 * 1. The name of a declaration is a NCName, not a QName.
2545 * 2. The attribute "targetNamespace" is allowed for the
2546 * <schema> Element Information Item only.
2547 * 3. One cannot evaluate the target namespace, by the type
2548 * of declaration, since it is dependant on the xxxFormDefault
2549 * of <schema> and the form attribute of an <element> or <attribute>.
2550 */
2551
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002552 if (xmlStrEqual(node->name, BAD_CAST "element") ||
2553 xmlStrEqual(node->name, BAD_CAST "attribute") ||
2554 xmlStrEqual(node->name, BAD_CAST "simpleType") ||
2555 xmlStrEqual(node->name, BAD_CAST "complexType")) {
2556 def = xmlSchemaGetProp(ctxt, node, "targetNamespace");
2557 }
2558
William M. Bracke7091952004-05-11 15:09:58 +00002559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002560 qname = xmlDictLookup(ctxt->dict, qname, -1); /* intern the string */
2561 name = xmlSplitQName3(qname, &len);
2562 if (name == NULL) {
2563 if (def == NULL) {
2564 if (xmlStrEqual(node->name, BAD_CAST "element")) {
2565 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
2566 *namespace = schema->targetNamespace;
2567 } else if (xmlStrEqual(node->name, BAD_CAST "attribute")) {
2568 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
2569 *namespace = schema->targetNamespace;
2570 } else if ((xmlStrEqual(node->name, BAD_CAST "simpleType")) ||
2571 (xmlStrEqual(node->name, BAD_CAST "complexType"))) {
2572 *namespace = schema->targetNamespace;
2573 }
2574 } else {
2575 *namespace = def;
2576 }
2577 return(qname);
2578 }
William M. Bracke7091952004-05-11 15:09:58 +00002579
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002580 name = xmlDictLookup(ctxt->dict, name, -1);
2581 prefix = xmlDictLookup(ctxt->dict, qname, len);
2582 if (def != NULL) {
2583 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_DEF_AND_PREFIX,
2584 "%s: presence of both prefix %s and targetNamespace\n",
2585 node->name, prefix);
2586 }
2587 ns = xmlSearchNs(node->doc, node, prefix);
2588 if (ns == NULL) {
2589 xmlSchemaPErr(ctxt, node, XML_SCHEMAP_PREFIX_UNDEFINED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002590 "%s: The QName prefix %s is undefined\n",
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002591 node->name, prefix);
2592 return(name);
2593 }
2594 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
2595 return(name);
2596}
William M. Brack29aa7722004-05-12 00:27:56 +00002597#endif
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002598
2599/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002600 * *
2601 * Parsing functions *
2602 * *
2603 ************************************************************************/
2604
2605/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002606 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002607 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002608 * @name: the element name
2609 * @ns: the element namespace
2610 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002611 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002612 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002613 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002614 */
2615static xmlSchemaElementPtr
2616xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002617 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002618{
2619 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620
2621 if ((name == NULL) || (schema == NULL))
2622 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002623
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002624 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002625 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002626 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002627 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002628 } else
2629 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002630 /*
2631 * This one was removed, since top level element declarations have
2632 * the target namespace specified in targetNamespace of the <schema>
2633 * information element, even if elementFormDefault is "unqualified".
2634 */
2635
2636 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002637 if (xmlStrEqual(namespace, schema->targetNamespace))
2638 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2639 else
2640 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002641 if ((ret != NULL) &&
2642 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002643 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002644 }
William M. Bracke7091952004-05-11 15:09:58 +00002645 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002646
William M. Brack2f2a6632004-08-20 23:09:47 +00002647 /*
2648 * Removed since imported components will be hold by the main schema only.
2649 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002650 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002651 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002652 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002653 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002654 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002655 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002656 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2657 return (ret);
2658 } else
2659 ret = NULL;
2660 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002661 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002662#ifdef DEBUG
2663 if (ret == NULL) {
2664 if (namespace == NULL)
2665 fprintf(stderr, "Unable to lookup type %s", name);
2666 else
2667 fprintf(stderr, "Unable to lookup type %s:%s", name,
2668 namespace);
2669 }
2670#endif
2671 return (ret);
2672}
2673
2674/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002675 * xmlSchemaGetType:
2676 * @schema: the schemas context
2677 * @name: the type name
2678 * @ns: the type namespace
2679 *
2680 * Lookup a type in the schemas or the predefined types
2681 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002682 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 */
2684static xmlSchemaTypePtr
2685xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 const xmlChar * namespace)
2687{
Daniel Veillard4255d502002-04-16 15:50:10 +00002688 xmlSchemaTypePtr ret;
2689
2690 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002693 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002694 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 }
2697 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002698 if (ret != NULL)
2699 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002700 /*
2701 * Removed, since the imported components will be grafted on the
2702 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002703 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002704 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002705 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002706 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002707 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002708 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002709 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2710 return (ret);
2711 } else
2712 ret = NULL;
2713 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002714 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002715#ifdef DEBUG
2716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 if (namespace == NULL)
2718 fprintf(stderr, "Unable to lookup type %s", name);
2719 else
2720 fprintf(stderr, "Unable to lookup type %s:%s", name,
2721 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 }
2723#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002725}
2726
Daniel Veillard3646d642004-06-02 19:19:14 +00002727/**
2728 * xmlSchemaGetAttribute:
2729 * @schema: the context of the schema
2730 * @name: the name of the attribute
2731 * @ns: the target namespace of the attribute
2732 *
2733 * Lookup a an attribute in the schema or imported schemas
2734 *
2735 * Returns the attribute declaration or NULL if not found.
2736 */
2737static xmlSchemaAttributePtr
2738xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2739 const xmlChar * namespace)
2740{
2741 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002742
2743 if ((name == NULL) || (schema == NULL))
2744 return (NULL);
2745
2746
2747 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2748 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2749 return (ret);
2750 else
2751 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002752 /*
2753 * Removed, since imported components will be hold by the main schema only.
2754 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002755 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002756 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002757 else
2758 import = xmlHashLookup(schema->schemasImports, namespace);
2759 if (import != NULL) {
2760 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2761 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2762 return (ret);
2763 } else
2764 ret = NULL;
2765 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002766 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002767#ifdef DEBUG
2768 if (ret == NULL) {
2769 if (namespace == NULL)
2770 fprintf(stderr, "Unable to lookup attribute %s", name);
2771 else
2772 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2773 namespace);
2774 }
2775#endif
2776 return (ret);
2777}
2778
2779/**
2780 * xmlSchemaGetAttributeGroup:
2781 * @schema: the context of the schema
2782 * @name: the name of the attribute group
2783 * @ns: the target namespace of the attribute group
2784 *
2785 * Lookup a an attribute group in the schema or imported schemas
2786 *
2787 * Returns the attribute group definition or NULL if not found.
2788 */
2789static xmlSchemaAttributeGroupPtr
2790xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2791 const xmlChar * namespace)
2792{
2793 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002794
2795 if ((name == NULL) || (schema == NULL))
2796 return (NULL);
2797
2798
2799 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2800 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2801 return (ret);
2802 else
2803 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002804 /*
2805 * Removed since imported components will be hold by the main schema only.
2806 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002807 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002808 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002809 else
2810 import = xmlHashLookup(schema->schemasImports, namespace);
2811 if (import != NULL) {
2812 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2813 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2814 return (ret);
2815 else
2816 ret = NULL;
2817 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002818 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002819#ifdef DEBUG
2820 if (ret == NULL) {
2821 if (namespace == NULL)
2822 fprintf(stderr, "Unable to lookup attribute group %s", name);
2823 else
2824 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2825 namespace);
2826 }
2827#endif
2828 return (ret);
2829}
2830
2831/**
2832 * xmlSchemaGetGroup:
2833 * @schema: the context of the schema
2834 * @name: the name of the group
2835 * @ns: the target namespace of the group
2836 *
2837 * Lookup a group in the schema or imported schemas
2838 *
2839 * Returns the group definition or NULL if not found.
2840 */
2841static xmlSchemaTypePtr
2842xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2843 const xmlChar * namespace)
2844{
2845 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002846
2847 if ((name == NULL) || (schema == NULL))
2848 return (NULL);
2849
2850
2851 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2852 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2853 return (ret);
2854 else
2855 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002856 /*
2857 * Removed since imported components will be hold by the main schema only.
2858 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002859 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002860 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002861 else
2862 import = xmlHashLookup(schema->schemasImports, namespace);
2863 if (import != NULL) {
2864 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2865 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2866 return (ret);
2867 else
2868 ret = NULL;
2869 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002870 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002871#ifdef DEBUG
2872 if (ret == NULL) {
2873 if (namespace == NULL)
2874 fprintf(stderr, "Unable to lookup group %s", name);
2875 else
2876 fprintf(stderr, "Unable to lookup group %s:%s", name,
2877 namespace);
2878 }
2879#endif
2880 return (ret);
2881}
2882
Daniel Veillard4255d502002-04-16 15:50:10 +00002883/************************************************************************
2884 * *
2885 * Parsing functions *
2886 * *
2887 ************************************************************************/
2888
2889#define IS_BLANK_NODE(n) \
2890 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2891
2892/**
2893 * xmlSchemaIsBlank:
2894 * @str: a string
2895 *
2896 * Check if a string is ignorable
2897 *
2898 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2899 */
2900static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002901xmlSchemaIsBlank(xmlChar * str)
2902{
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002904 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002905 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002906 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002907 return (0);
2908 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002909 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002910 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002911}
2912
2913/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002914 * xmlSchemaAddAssembledItem:
2915 * @ctxt: a schema parser context
2916 * @schema: the schema being built
2917 * @item: the item
2918 *
2919 * Add a item to the schema's list of current items.
2920 * This is used if the schema was already constructed and
2921 * new schemata need to be added to it.
2922 * *WARNING* this interface is highly subject to change.
2923 *
2924 * Returns 0 if suceeds and -1 if an internal error occurs.
2925 */
2926static int
2927xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2928 xmlSchemaTypePtr item)
2929{
2930 static int growSize = 100;
2931 xmlSchemaAssemblePtr ass;
2932
2933 ass = ctxt->assemble;
2934 if (ass->sizeItems < 0) {
2935 /* If disabled. */
2936 return (0);
2937 }
2938 if (ass->sizeItems <= 0) {
2939 ass->items = xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
2940 if (ass->items == NULL) {
2941 xmlSchemaPErrMemory(ctxt,
2942 "allocating new item buffer", NULL);
2943 return (-1);
2944 }
2945 ass->sizeItems = growSize;
2946 } else if (ass->sizeItems <= ass->nbItems) {
2947 ass->sizeItems *= 2;
2948 ass->items = (xmlNsPtr *) xmlRealloc(ass->items,
2949 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2950 if (ass->items == NULL) {
2951 xmlSchemaPErrMemory(ctxt,
2952 "growing item buffer", NULL);
2953 ass->sizeItems = 0;
2954 return (-1);
2955 }
2956 }
2957 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2958 return (0);
2959}
2960
2961/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002962 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002963 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002964 * @schema: the schema being built
2965 * @name: the item name
2966 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002967 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002968 * *WARNING* this interface is highly subject to change
2969 *
2970 * Returns the new struture or NULL in case of error
2971 */
2972static xmlSchemaNotationPtr
2973xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002974 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002975{
2976 xmlSchemaNotationPtr ret = NULL;
2977 int val;
2978
2979 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2980 return (NULL);
2981
2982 if (schema->notaDecl == NULL)
2983 schema->notaDecl = xmlHashCreate(10);
2984 if (schema->notaDecl == NULL)
2985 return (NULL);
2986
2987 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2988 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002989 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002990 return (NULL);
2991 }
2992 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002993 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002994 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2995 ret);
2996 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002997 /*
2998 * TODO: This should never happen, since a unique name will be computed.
2999 * If it fails, then an other internal error must have occured.
3000 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003001 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3002 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003003 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003004 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003005 xmlFree(ret);
3006 return (NULL);
3007 }
3008 return (ret);
3009}
3010
3011
3012/**
3013 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003014 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003015 * @schema: the schema being built
3016 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003017 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003018 *
3019 * Add an XML schema Attrribute declaration
3020 * *WARNING* this interface is highly subject to change
3021 *
3022 * Returns the new struture or NULL in case of error
3023 */
3024static xmlSchemaAttributePtr
3025xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003026 const xmlChar * name, const xmlChar * namespace,
3027 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003028{
3029 xmlSchemaAttributePtr ret = NULL;
3030 int val;
3031
3032 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3033 return (NULL);
3034
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003035#ifdef DEBUG
3036 fprintf(stderr, "Adding attribute %s\n", name);
3037 if (namespace != NULL)
3038 fprintf(stderr, " target namespace %s\n", namespace);
3039#endif
3040
Daniel Veillard4255d502002-04-16 15:50:10 +00003041 if (schema->attrDecl == NULL)
3042 schema->attrDecl = xmlHashCreate(10);
3043 if (schema->attrDecl == NULL)
3044 return (NULL);
3045
3046 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3047 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003048 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003049 return (NULL);
3050 }
3051 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003052 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3053 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003054 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003055 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003056 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003057 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003058 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003059 NULL, NULL, node,
3060 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003061 xmlFree(ret);
3062 return (NULL);
3063 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003064 if (ctxt->assemble != NULL)
3065 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 return (ret);
3067}
3068
3069/**
3070 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003071 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 * @schema: the schema being built
3073 * @name: the item name
3074 *
3075 * Add an XML schema Attrribute Group declaration
3076 *
3077 * Returns the new struture or NULL in case of error
3078 */
3079static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003080xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003081 xmlSchemaPtr schema, const xmlChar * name,
3082 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003083{
3084 xmlSchemaAttributeGroupPtr ret = NULL;
3085 int val;
3086
3087 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3088 return (NULL);
3089
3090 if (schema->attrgrpDecl == NULL)
3091 schema->attrgrpDecl = xmlHashCreate(10);
3092 if (schema->attrgrpDecl == NULL)
3093 return (NULL);
3094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003095 ret =
3096 (xmlSchemaAttributeGroupPtr)
3097 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003098 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003099 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003100 return (NULL);
3101 }
3102 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003104 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003105 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003106 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003107 xmlSchemaPCustomErr(ctxt,
3108 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3109 NULL, NULL, node,
3110 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003111 xmlFree(ret);
3112 return (NULL);
3113 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003114 if (ctxt->assemble != NULL)
3115 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 return (ret);
3117}
3118
3119/**
3120 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003121 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003122 * @schema: the schema being built
3123 * @name: the type name
3124 * @namespace: the type namespace
3125 *
3126 * Add an XML schema Element declaration
3127 * *WARNING* this interface is highly subject to change
3128 *
3129 * Returns the new struture or NULL in case of error
3130 */
3131static xmlSchemaElementPtr
3132xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003133 const xmlChar * name, const xmlChar * namespace,
3134 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003135{
3136 xmlSchemaElementPtr ret = NULL;
3137 int val;
3138
3139 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3140 return (NULL);
3141
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003142#ifdef DEBUG
3143 fprintf(stderr, "Adding element %s\n", name);
3144 if (namespace != NULL)
3145 fprintf(stderr, " target namespace %s\n", namespace);
3146#endif
3147
Daniel Veillard4255d502002-04-16 15:50:10 +00003148 if (schema->elemDecl == NULL)
3149 schema->elemDecl = xmlHashCreate(10);
3150 if (schema->elemDecl == NULL)
3151 return (NULL);
3152
3153 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3154 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003155 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003156 return (NULL);
3157 }
3158 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003159 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3160 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003161 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003162 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003163 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003164 if (topLevel) {
3165 xmlSchemaPCustomErr(ctxt,
3166 XML_SCHEMAP_REDEFINED_ELEMENT,
3167 NULL, NULL, node,
3168 "A global element declaration with the name '%s' does "
3169 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003170 xmlFree(ret);
3171 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003172 } else {
3173 char buf[30];
3174
3175 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3176 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3177 namespace, ret);
3178 if (val != 0) {
3179 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003180 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003181 NULL, NULL, node,
3182 "Internal error: xmlSchemaAddElement, "
3183 "a dublicate element declaration with the name '%s' "
3184 "could not be added to the hash.", name);
3185 xmlFree(ret);
3186 return (NULL);
3187 }
3188 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003189
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003191 if (ctxt->assemble != NULL)
3192 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003193 return (ret);
3194}
3195
3196/**
3197 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003198 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 * @schema: the schema being built
3200 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003201 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003203 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 * *WARNING* this interface is highly subject to change
3205 *
3206 * Returns the new struture or NULL in case of error
3207 */
3208static xmlSchemaTypePtr
3209xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003210 const xmlChar * name, const xmlChar * namespace,
3211 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003212{
3213 xmlSchemaTypePtr ret = NULL;
3214 int val;
3215
3216 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3217 return (NULL);
3218
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003219#ifdef DEBUG
3220 fprintf(stderr, "Adding type %s\n", name);
3221 if (namespace != NULL)
3222 fprintf(stderr, " target namespace %s\n", namespace);
3223#endif
3224
Daniel Veillard4255d502002-04-16 15:50:10 +00003225 if (schema->typeDecl == NULL)
3226 schema->typeDecl = xmlHashCreate(10);
3227 if (schema->typeDecl == NULL)
3228 return (NULL);
3229
3230 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3231 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003232 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003233 return (NULL);
3234 }
3235 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003236 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003237 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003238 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003239 if (val != 0) {
3240 if (ctxt->includes == 0) {
3241 xmlSchemaPCustomErr(ctxt,
3242 XML_SCHEMAP_REDEFINED_TYPE,
3243 NULL, NULL, node,
3244 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003245 xmlFree(ret);
3246 return (NULL);
3247 } else {
3248 xmlSchemaTypePtr prev;
3249
3250 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3251 if (prev == NULL) {
3252 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003253 XML_ERR_INTERNAL_ERROR,
3254 "Internal error: xmlSchemaAddType, on type "
3255 "'%s'.\n",
3256 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003257 xmlFree(ret);
3258 return (NULL);
3259 }
3260 ret->redef = prev->redef;
3261 prev->redef = ret;
3262 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003263 }
3264 ret->minOccurs = 1;
3265 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003266 ret->attributeUses = NULL;
3267 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003268 if (ctxt->assemble != NULL)
3269 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003270 return (ret);
3271}
3272
3273/**
3274 * xmlSchemaAddGroup:
3275 * @ctxt: a schema validation context
3276 * @schema: the schema being built
3277 * @name: the group name
3278 *
3279 * Add an XML schema Group definition
3280 *
3281 * Returns the new struture or NULL in case of error
3282 */
3283static xmlSchemaTypePtr
3284xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003285 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003286{
3287 xmlSchemaTypePtr ret = NULL;
3288 int val;
3289
3290 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3291 return (NULL);
3292
3293 if (schema->groupDecl == NULL)
3294 schema->groupDecl = xmlHashCreate(10);
3295 if (schema->groupDecl == NULL)
3296 return (NULL);
3297
3298 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3299 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003300 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003301 return (NULL);
3302 }
3303 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003304 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003305 val =
3306 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3307 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003308 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003309 xmlSchemaPCustomErr(ctxt,
3310 XML_SCHEMAP_REDEFINED_GROUP,
3311 NULL, NULL, node,
3312 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003313 xmlFree(ret);
3314 return (NULL);
3315 }
3316 ret->minOccurs = 1;
3317 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003318 if (ctxt->assemble != NULL)
3319 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003320 return (ret);
3321}
3322
Daniel Veillard3646d642004-06-02 19:19:14 +00003323/**
3324 * xmlSchemaNewWildcardNs:
3325 * @ctxt: a schema validation context
3326 *
3327 * Creates a new wildcard namespace constraint.
3328 *
3329 * Returns the new struture or NULL in case of error
3330 */
3331static xmlSchemaWildcardNsPtr
3332xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3333{
3334 xmlSchemaWildcardNsPtr ret;
3335
3336 ret = (xmlSchemaWildcardNsPtr)
3337 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3338 if (ret == NULL) {
3339 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3340 return (NULL);
3341 }
3342 ret->value = NULL;
3343 ret->next = NULL;
3344 return (ret);
3345}
3346
3347/**
3348 * xmlSchemaAddWildcard:
3349 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003350 * Adds a wildcard. It corresponds to a
3351 * xsd:anyAttribute and is used as storage for namespace
3352 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003353 *
3354 * Returns the new struture or NULL in case of error
3355 */
3356static xmlSchemaWildcardPtr
3357xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3358{
3359 xmlSchemaWildcardPtr ret = NULL;
3360
3361 if (ctxt == NULL)
3362 return (NULL);
3363
3364 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3365 if (ret == NULL) {
3366 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3367 return (NULL);
3368 }
3369 memset(ret, 0, sizeof(xmlSchemaWildcard));
3370 ret->minOccurs = 1;
3371 ret->maxOccurs = 1;
3372
3373 return (ret);
3374}
3375
Daniel Veillard4255d502002-04-16 15:50:10 +00003376/************************************************************************
3377 * *
3378 * Utilities for parsing *
3379 * *
3380 ************************************************************************/
3381
3382/**
3383 * xmlGetQNameProp:
3384 * @ctxt: a schema validation context
3385 * @node: a subtree containing XML Schema informations
3386 * @name: the attribute name
3387 * @namespace: the result namespace if any
3388 *
3389 * Extract a QName Attribute value
3390 *
3391 * Returns the NCName or NULL if not found, and also update @namespace
3392 * with the namespace URI
3393 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003394static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003395xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003396 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003398 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003400 const xmlChar *ret, *prefix;
3401 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003402 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003403
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003404 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003405 attr = xmlSchemaGetPropNode(node, name);
3406 if (attr == NULL)
3407 return (NULL);
3408 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3409 /*
3410 * TODO: Is the empty value valid for QNames?
3411 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003412 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003414
Daniel Veillardba0153a2004-04-01 10:42:31 +00003415 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003416 ns = xmlSearchNs(node->doc, node, 0);
3417 if (ns) {
3418 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3419 return (val);
3420 }
3421 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003422 ret = xmlSplitQName3(val, &len);
3423 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003424 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003425 }
3426 ret = xmlDictLookup(ctxt->dict, ret, -1);
3427 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003428
3429 ns = xmlSearchNs(node->doc, node, prefix);
3430 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003431 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3432 NULL, NULL, (xmlNodePtr) attr,
3433 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003434 "The QName value '%s' has no corresponding namespace "
3435 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003436 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003437 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003438 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003439 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003440}
3441
3442/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003443 * xmlSchemaPValAttrNodeQNameValue:
3444 * @ctxt: a schema parser context
3445 * @schema: the schema context
3446 * @ownerDes: the designation of the parent element
3447 * @ownerItem: the parent as a schema object
3448 * @value: the QName value
3449 * @local: the resulting local part if found, the attribute value otherwise
3450 * @uri: the resulting namespace URI if found
3451 *
3452 * Extracts the local name and the URI of a QName value and validates it.
3453 * This one is intended to be used on attribute values that
3454 * should resolve to schema components.
3455 *
3456 * Returns 0, in case the QName is valid, a positive error code
3457 * if not valid and -1 if an internal error occurs.
3458 */
3459static int
3460xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3461 xmlSchemaPtr schema,
3462 xmlChar **ownerDes,
3463 xmlSchemaTypePtr ownerItem,
3464 xmlAttrPtr attr,
3465 const xmlChar *value,
3466 const xmlChar **uri,
3467 const xmlChar **prefix,
3468 const xmlChar **local)
3469{
3470 const xmlChar *pref;
3471 xmlNsPtr ns;
3472 int len, ret;
3473
3474 *uri = NULL;
3475 *local = NULL;
3476 if (prefix != 0)
3477 *prefix = NULL;
3478 ret = xmlValidateQName(value, 1);
3479 if (ret > 0) {
3480 xmlSchemaPSimpleTypeErr(ctxt,
3481 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3482 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003483 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3484 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003485 NULL, NULL, NULL);
3486 *local = value;
3487 return (ctxt->err);
3488 } else if (ret < 0)
3489 return (-1);
3490
3491 if (!strchr((char *) value, ':')) {
3492 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3493 if (ns)
3494 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3495 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3496 /*
3497 * This one takes care of included schemas with no
3498 * target namespace.
3499 */
3500 *uri = schema->targetNamespace;
3501 }
3502 *local = value;
3503 return (0);
3504 }
3505 /*
3506 * At this point xmlSplitQName3 has to return a local name.
3507 */
3508 *local = xmlSplitQName3(value, &len);
3509 *local = xmlDictLookup(ctxt->dict, *local, -1);
3510 pref = xmlDictLookup(ctxt->dict, value, len);
3511 if (prefix != 0)
3512 *prefix = pref;
3513 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3514 if (ns == NULL) {
3515 xmlSchemaPSimpleTypeErr(ctxt,
3516 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3517 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003518 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3519 "The QName value '%s' has no corresponding namespace "
3520 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003521 return (ctxt->err);
3522 } else {
3523 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3524 }
3525 return (0);
3526}
3527
3528/**
3529 * xmlSchemaPValAttrNodeQName:
3530 * @ctxt: a schema parser context
3531 * @schema: the schema context
3532 * @ownerDes: the designation of the owner element
3533 * @ownerItem: the owner as a schema object
3534 * @attr: the attribute node
3535 * @local: the resulting local part if found, the attribute value otherwise
3536 * @uri: the resulting namespace URI if found
3537 *
3538 * Extracts and validates the QName of an attribute value.
3539 * This one is intended to be used on attribute values that
3540 * should resolve to schema components.
3541 *
3542 * Returns 0, in case the QName is valid, a positive error code
3543 * if not valid and -1 if an internal error occurs.
3544 */
3545static int
3546xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3547 xmlSchemaPtr schema,
3548 xmlChar **ownerDes,
3549 xmlSchemaTypePtr ownerItem,
3550 xmlAttrPtr attr,
3551 const xmlChar **uri,
3552 const xmlChar **prefix,
3553 const xmlChar **local)
3554{
3555 const xmlChar *value;
3556
3557 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3558 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3559 ownerDes, ownerItem, attr, value, uri, prefix, local));
3560}
3561
3562/**
3563 * xmlSchemaPValAttrQName:
3564 * @ctxt: a schema parser context
3565 * @schema: the schema context
3566 * @ownerDes: the designation of the parent element
3567 * @ownerItem: the owner as a schema object
3568 * @ownerElem: the parent node of the attribute
3569 * @name: the name of the attribute
3570 * @local: the resulting local part if found, the attribute value otherwise
3571 * @uri: the resulting namespace URI if found
3572 *
3573 * Extracts and validates the QName of an attribute value.
3574 *
3575 * Returns 0, in case the QName is valid, a positive error code
3576 * if not valid and -1 if an internal error occurs.
3577 */
3578static int
3579xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3580 xmlSchemaPtr schema,
3581 xmlChar **ownerDes,
3582 xmlSchemaTypePtr ownerItem,
3583 xmlNodePtr ownerElem,
3584 const char *name,
3585 const xmlChar **uri,
3586 const xmlChar **prefix,
3587 const xmlChar **local)
3588{
3589 xmlAttrPtr attr;
3590
3591 attr = xmlSchemaGetPropNode(ownerElem, name);
3592 if (attr == NULL) {
3593 *local = NULL;
3594 *uri = NULL;
3595 return (0);
3596 }
3597 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3598 ownerDes, ownerItem, attr, uri, prefix, local));
3599}
3600
3601/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 * xmlGetMaxOccurs:
3603 * @ctxt: a schema validation context
3604 * @node: a subtree containing XML Schema informations
3605 *
3606 * Get the maxOccurs property
3607 *
3608 * Returns the default if not found, or the value
3609 */
3610static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003611xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3612 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003614 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003616 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003617
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003618 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3619 if (attr == NULL)
3620 return (def);
3621 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003622
3623 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003624 if (max != UNBOUNDED) {
3625 xmlSchemaPSimpleTypeErr(ctxt,
3626 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3627 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3628 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3629 val, NULL, NULL, NULL);
3630 return (def);
3631 } else
3632 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 }
3634
3635 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003636 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003637 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003638 if (*cur == 0) {
3639 xmlSchemaPSimpleTypeErr(ctxt,
3640 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3641 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3642 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3643 val, NULL, NULL, NULL);
3644 return (def);
3645 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 ret = ret * 10 + (*cur - '0');
3648 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 }
William M. Brack76e95df2003-10-18 16:20:14 +00003650 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003652 /*
3653 * TODO: Restrict the maximal value to Integer.
3654 */
3655 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3656 xmlSchemaPSimpleTypeErr(ctxt,
3657 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3658 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3659 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3660 val, NULL, NULL, NULL);
3661 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003662 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003663 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003664}
3665
3666/**
3667 * xmlGetMinOccurs:
3668 * @ctxt: a schema validation context
3669 * @node: a subtree containing XML Schema informations
3670 *
3671 * Get the minOccurs property
3672 *
3673 * Returns the default if not found, or the value
3674 */
3675static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003676xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3677 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003679 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003680 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003681 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003682
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003683 attr = xmlSchemaGetPropNode(node, "minOccurs");
3684 if (attr == NULL)
3685 return (def);
3686 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003687 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003688 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003689 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003690 if (*cur == 0) {
3691 xmlSchemaPSimpleTypeErr(ctxt,
3692 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3693 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3694 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3695 val, NULL, NULL, NULL);
3696 return (def);
3697 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003698 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003699 ret = ret * 10 + (*cur - '0');
3700 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 }
William M. Brack76e95df2003-10-18 16:20:14 +00003702 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003703 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003704 /*
3705 * TODO: Restrict the maximal value to Integer.
3706 */
3707 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3708 xmlSchemaPSimpleTypeErr(ctxt,
3709 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3710 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3711 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3712 val, NULL, NULL, NULL);
3713 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003714 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003715 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003716}
3717
3718/**
3719 * xmlGetBooleanProp:
3720 * @ctxt: a schema validation context
3721 * @node: a subtree containing XML Schema informations
3722 * @name: the attribute name
3723 * @def: the default value
3724 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003725 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 *
3727 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003728 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 */
3730static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003731xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3732 xmlChar **ownerDes,
3733 xmlSchemaTypePtr ownerItem,
3734 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003735 const char *name, int def)
3736{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003737 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003738
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003739 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003740 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003741 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003742 /*
3743 * 3.2.2.1 Lexical representation
3744 * An instance of a datatype that is defined as ·boolean·
3745 * can have the following legal literals {true, false, 1, 0}.
3746 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003747 if (xmlStrEqual(val, BAD_CAST "true"))
3748 def = 1;
3749 else if (xmlStrEqual(val, BAD_CAST "false"))
3750 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003751 else if (xmlStrEqual(val, BAD_CAST "1"))
3752 def = 1;
3753 else if (xmlStrEqual(val, BAD_CAST "0"))
3754 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003755 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003756 xmlSchemaPSimpleTypeErr(ctxt,
3757 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003758 ownerDes, ownerItem, node,
3759 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3760 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003761 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003762 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003763}
3764
3765/************************************************************************
3766 * *
3767 * Shema extraction from an Infoset *
3768 * *
3769 ************************************************************************/
3770static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3771 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003772 xmlNodePtr node,
3773 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003774static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3775 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003776 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003777 xmlNodePtr node,
3778 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003779static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3780 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003781 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003782 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003783static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3784 xmlSchemaPtr schema,
3785 xmlNodePtr node);
3786static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3787 xmlSchemaPtr schema,
3788 xmlNodePtr node);
3789static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3790 ctxt,
3791 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003792 xmlNodePtr node,
3793 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003794static xmlSchemaAttributeGroupPtr
3795xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003796 xmlSchemaPtr schema, xmlNodePtr node,
3797 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003798static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3799 xmlSchemaPtr schema,
3800 xmlNodePtr node);
3801static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3802 xmlSchemaPtr schema,
3803 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003804static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003805xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3806 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003807
3808/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003809 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003810 *
3811 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003812 * @ownerDes: the designation of the parent element
3813 * @ownerItem: the schema object owner if existent
3814 * @attr: the schema attribute node being validated
3815 * @value: the value
3816 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003817 *
3818 * Validates a value against the given built-in type.
3819 * This one is intended to be used internally for validation
3820 * of schema attribute values during parsing of the schema.
3821 *
3822 * Returns 0 if the value is valid, a positive error code
3823 * number otherwise and -1 in case of an internal or API error.
3824 */
3825static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003826xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3827 xmlChar **ownerDes,
3828 xmlSchemaTypePtr ownerItem,
3829 xmlAttrPtr attr,
3830 const xmlChar *value,
3831 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003832{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003833
Daniel Veillardc0826a72004-08-10 14:17:33 +00003834 int ret = 0;
3835
3836 /*
3837 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3838 * one is really meant to be used internally, so better not.
3839 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003840 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003841 return (-1);
3842 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3843 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003844 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003845 "Internal error: xmlSchemaPvalueAttrNode, the given "
3846 "type '%s' is not a built-in type.\n",
3847 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003848 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003849 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003850 switch (type->builtInType) {
3851 case XML_SCHEMAS_NCNAME:
3852 ret = xmlValidateNCName(value, 1);
3853 break;
3854 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003855 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003856 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003857 "Internal error: xmlSchemaPvalueAttrNode, use "
3858 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3859 "for extracting QName valueues instead.\n",
3860 NULL, NULL);
3861 return (-1);
3862 case XML_SCHEMAS_ANYURI:
3863 if (value != NULL) {
3864 xmlURIPtr uri = xmlParseURI((const char *) value);
3865 if (uri == NULL)
3866 ret = 1;
3867 else
3868 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003869 }
3870 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003871 case XML_SCHEMAS_TOKEN: {
3872 const xmlChar *cur = value;
3873
3874 if (IS_BLANK_CH(*cur)) {
3875 ret = 1;
3876 } else while (*cur != 0) {
3877 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3878 ret = 1;
3879 break;
3880 } else if (*cur == ' ') {
3881 cur++;
3882 if ((*cur == 0) || (*cur == ' ')) {
3883 ret = 1;
3884 break;
3885 }
3886 } else {
3887 cur++;
3888 }
3889 }
3890 }
3891 break;
3892 case XML_SCHEMAS_LANGUAGE:
3893 if (xmlCheckLanguageID(value) != 1)
3894 ret = 1;
3895 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00003896 default: {
3897 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003898 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003899 "Internal error: xmlSchemaPvalueAttrNode, "
3900 "valueidation using the type '%s' is not implemented "
3901 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003902 type->name, NULL);
3903 return (-1);
3904 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003905 }
3906 /*
3907 * TODO: Should we use the S4S error codes instead?
3908 */
3909 if (ret > 0) {
3910 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3911 xmlSchemaPSimpleTypeErr(ctxt,
3912 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3913 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003914 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003915 NULL, NULL, NULL);
3916 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3917 } else {
3918 xmlSchemaPSimpleTypeErr(ctxt,
3919 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3920 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003921 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003922 NULL, NULL, NULL);
3923 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3924 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003925 }
3926 return (ret);
3927}
3928
3929/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003930 * xmlSchemaPValAttrNode:
3931 *
3932 * @ctxt: a schema parser context
3933 * @ownerDes: the designation of the parent element
3934 * @ownerItem: the schema object owner if existent
3935 * @attr: the schema attribute node being validated
3936 * @type: the built-in type to be validated against
3937 * @value: the resulting value if any
3938 *
3939 * Extracts and validates a value against the given built-in type.
3940 * This one is intended to be used internally for validation
3941 * of schema attribute values during parsing of the schema.
3942 *
3943 * Returns 0 if the value is valid, a positive error code
3944 * number otherwise and -1 in case of an internal or API error.
3945 */
3946static int
3947xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3948 xmlChar **ownerDes,
3949 xmlSchemaTypePtr ownerItem,
3950 xmlAttrPtr attr,
3951 xmlSchemaTypePtr type,
3952 const xmlChar **value)
3953{
3954 const xmlChar *val;
3955
3956 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3957 return (-1);
3958
3959 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3960 if (value != NULL)
3961 *value = val;
3962
3963 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3964 val, type));
3965}
3966
3967/**
3968 * xmlSchemaPValAttr:
3969 *
3970 * @ctxt: a schema parser context
3971 * @node: the element node of the attribute
3972 * @ownerDes: the designation of the parent element
3973 * @ownerItem: the schema object owner if existent
3974 * @ownerElem: the owner element node
3975 * @name: the name of the schema attribute node
3976 * @type: the built-in type to be validated against
3977 * @value: the resulting value if any
3978 *
3979 * Extracts and validates a value against the given built-in type.
3980 * This one is intended to be used internally for validation
3981 * of schema attribute values during parsing of the schema.
3982 *
3983 * Returns 0 if the value is valid, a positive error code
3984 * number otherwise and -1 in case of an internal or API error.
3985 */
3986static int
3987xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
3988 xmlChar **ownerDes,
3989 xmlSchemaTypePtr ownerItem,
3990 xmlNodePtr ownerElem,
3991 const char *name,
3992 xmlSchemaTypePtr type,
3993 const xmlChar **value)
3994{
3995 xmlAttrPtr attr;
3996
3997 if ((ctxt == NULL) || (type == NULL)) {
3998 if (value != NULL)
3999 *value = NULL;
4000 return (-1);
4001 }
4002 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4003 if (value != NULL)
4004 *value = NULL;
4005 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004006 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004007 "Internal error: xmlSchemaPValAttr, the given "
4008 "type '%s' is not a built-in type.\n",
4009 type->name, NULL);
4010 return (-1);
4011 }
4012 attr = xmlSchemaGetPropNode(ownerElem, name);
4013 if (attr == NULL) {
4014 if (value != NULL)
4015 *value = NULL;
4016 return (0);
4017 }
4018 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4019 type, value));
4020}
4021/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004022 * xmlSchemaParseAttrDecls:
4023 * @ctxt: a schema validation context
4024 * @schema: the schema being built
4025 * @node: a subtree containing XML Schema informations
4026 * @type: the hosting type
4027 *
4028 * parse a XML schema attrDecls declaration corresponding to
4029 * <!ENTITY % attrDecls
4030 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4031 */
4032static xmlNodePtr
4033xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4034 xmlNodePtr child, xmlSchemaTypePtr type)
4035{
4036 xmlSchemaAttributePtr lastattr, attr;
4037
4038 lastattr = NULL;
4039 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004040 (IS_SCHEMA(child, "attributeGroup"))) {
4041 attr = NULL;
4042 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004043 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004044 } else if (IS_SCHEMA(child, "attributeGroup")) {
4045 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004046 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004047 }
4048 if (attr != NULL) {
4049 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004050 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4051 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4052 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 type->attributes = attr;
4054 lastattr = attr;
4055 } else {
4056 lastattr->next = attr;
4057 lastattr = attr;
4058 }
4059 }
4060 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004061 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004062 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004063}
4064
4065/**
4066 * xmlSchemaParseAnnotation:
4067 * @ctxt: a schema validation context
4068 * @schema: the schema being built
4069 * @node: a subtree containing XML Schema informations
4070 *
4071 * parse a XML schema Attrribute declaration
4072 * *WARNING* this interface is highly subject to change
4073 *
William M. Bracke7091952004-05-11 15:09:58 +00004074 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004075 * 1 in case of success.
4076 */
4077static xmlSchemaAnnotPtr
4078xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4079 xmlNodePtr node)
4080{
4081 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004082 xmlNodePtr child = NULL;
4083 xmlAttrPtr attr;
4084 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004085
Daniel Veillardc0826a72004-08-10 14:17:33 +00004086 /*
4087 * INFO: S4S completed.
4088 */
4089 /*
4090 * id = ID
4091 * {any attributes with non-schema namespace . . .}>
4092 * Content: (appinfo | documentation)*
4093 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004094 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4095 return (NULL);
4096 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004097 attr = node->properties;
4098 while (attr != NULL) {
4099 if (((attr->ns == NULL) &&
4100 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4101 ((attr->ns != NULL) &&
4102 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4103
4104 xmlSchemaPIllegalAttrErr(ctxt,
4105 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4106 NULL, NULL, attr);
4107 }
4108 attr = attr->next;
4109 }
4110 /* TODO: Check id. */
4111
4112 /*
4113 * And now for the children...
4114 */
4115 child = node->children;
4116 while (child != NULL) {
4117 if (IS_SCHEMA(child, "appinfo")) {
4118 /* TODO: make available the content of "appinfo". */
4119 /*
4120 * source = anyURI
4121 * {any attributes with non-schema namespace . . .}>
4122 * Content: ({any})*
4123 */
4124 attr = child->properties;
4125 while (attr != NULL) {
4126 if (((attr->ns == NULL) &&
4127 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4128 ((attr->ns != NULL) &&
4129 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004130
Daniel Veillardc0826a72004-08-10 14:17:33 +00004131 xmlSchemaPIllegalAttrErr(ctxt,
4132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4133 NULL, NULL, attr);
4134 }
4135 attr = attr->next;
4136 }
4137 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4138 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4139 child = child->next;
4140 } else if (IS_SCHEMA(child, "documentation")) {
4141 /* TODO: make available the content of "documentation". */
4142 /*
4143 * source = anyURI
4144 * {any attributes with non-schema namespace . . .}>
4145 * Content: ({any})*
4146 */
4147 attr = child->properties;
4148 while (attr != NULL) {
4149 if (attr->ns == NULL) {
4150 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4151 xmlSchemaPIllegalAttrErr(ctxt,
4152 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4153 NULL, NULL, attr);
4154 }
4155 } else {
4156 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4157 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4158 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4159
4160 xmlSchemaPIllegalAttrErr(ctxt,
4161 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4162 NULL, NULL, attr);
4163 }
4164 }
4165 attr = attr->next;
4166 }
4167 /*
4168 * Attribute "xml:lang".
4169 */
4170 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4171 if (attr != NULL)
4172 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4173 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4174 child = child->next;
4175 } else {
4176 if (!barked)
4177 xmlSchemaPContentErr(ctxt,
4178 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4179 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4180 barked = 1;
4181 child = child->next;
4182 }
4183 }
4184
Daniel Veillard4255d502002-04-16 15:50:10 +00004185 return (ret);
4186}
4187
4188/**
4189 * xmlSchemaParseFacet:
4190 * @ctxt: a schema validation context
4191 * @schema: the schema being built
4192 * @node: a subtree containing XML Schema informations
4193 *
4194 * parse a XML schema Facet declaration
4195 * *WARNING* this interface is highly subject to change
4196 *
4197 * Returns the new type structure or NULL in case of error
4198 */
4199static xmlSchemaFacetPtr
4200xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004201 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004202{
4203 xmlSchemaFacetPtr facet;
4204 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004205 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004206
4207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4208 return (NULL);
4209
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004210 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004211 if (facet == NULL) {
4212 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4213 return (NULL);
4214 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004215 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004216 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4219 "Facet %s has no value\n", node->name, NULL);
4220 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004221 return (NULL);
4222 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004223 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004224 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004225 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004226 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004228 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004229 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004230 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004231 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004232 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004234 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004237 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004239 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004240 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004241 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004243 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4245 } else if (IS_SCHEMA(node, "minLength")) {
4246 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4247 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004248 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4249 "Unknown facet type %s\n", node->name, NULL);
4250 xmlSchemaFreeFacet(facet);
4251 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004252 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004253 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004254 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004255 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4256 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4257 const xmlChar *fixed;
4258
4259 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4260 if (fixed != NULL) {
4261 if (xmlStrEqual(fixed, BAD_CAST "true"))
4262 facet->fixed = 1;
4263 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004264 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004265 child = node->children;
4266
4267 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004268 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4269 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 }
4271 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004272 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4273 "Facet %s has unexpected child content\n",
4274 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 }
4276 return (facet);
4277}
4278
4279/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004280 * xmlSchemaParseWildcardNs:
4281 * @ctxt: a schema parser context
4282 * @wildc: the wildcard, already created
4283 * @node: a subtree containing XML Schema informations
4284 *
4285 * Parses the attribute "processContents" and "namespace"
4286 * of a xsd:anyAttribute and xsd:any.
4287 * *WARNING* this interface is highly subject to change
4288 *
4289 * Returns 0 if everything goes fine, a positive error code
4290 * if something is not valid and -1 if an internal error occurs.
4291 */
4292static int
4293xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4294 xmlSchemaPtr schema,
4295 xmlSchemaWildcardPtr wildc,
4296 xmlNodePtr node)
4297{
4298 const xmlChar *pc, *ns, *dictnsItem;
4299 int ret = 0;
4300 xmlChar *nsItem;
4301 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4302 xmlAttrPtr attr;
4303
4304 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4305 if ((pc == NULL)
4306 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4307 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4308 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4309 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4310 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4311 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4312 } else {
4313 xmlSchemaPSimpleTypeErr(ctxt,
4314 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4315 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004316 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004317 NULL, NULL, NULL);
4318 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4319 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4320 }
4321 /*
4322 * Build the namespace constraints.
4323 */
4324 attr = xmlSchemaGetPropNode(node, "namespace");
4325 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4326 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4327 wildc->any = 1;
4328 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4329 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4330 if (wildc->negNsSet == NULL) {
4331 return (-1);
4332 }
4333 wildc->negNsSet->value = schema->targetNamespace;
4334 } else {
4335 const xmlChar *end, *cur;
4336
4337 cur = ns;
4338 do {
4339 while (IS_BLANK_CH(*cur))
4340 cur++;
4341 end = cur;
4342 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4343 end++;
4344 if (end == cur)
4345 break;
4346 nsItem = xmlStrndup(cur, end - cur);
4347 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4348 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4349 xmlSchemaPSimpleTypeErr(ctxt,
4350 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4351 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004352 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004353 "((##any | ##other) | List of (anyURI | "
4354 "(##targetNamespace | ##local)))",
4355 nsItem, NULL, NULL, NULL);
4356 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4357 } else {
4358 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4359 dictnsItem = schema->targetNamespace;
4360 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4361 dictnsItem = NULL;
4362 } else {
4363 /*
4364 * Validate the item (anyURI).
4365 */
4366 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4367 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4368 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4369 }
4370 /*
4371 * Avoid dublicate namespaces.
4372 */
4373 tmp = wildc->nsSet;
4374 while (tmp != NULL) {
4375 if (dictnsItem == tmp->value)
4376 break;
4377 tmp = tmp->next;
4378 }
4379 if (tmp == NULL) {
4380 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4381 if (tmp == NULL) {
4382 xmlFree(nsItem);
4383 return (-1);
4384 }
4385 tmp->value = dictnsItem;
4386 tmp->next = NULL;
4387 if (wildc->nsSet == NULL)
4388 wildc->nsSet = tmp;
4389 else
4390 lastNs->next = tmp;
4391 lastNs = tmp;
4392 }
4393
4394 }
4395 xmlFree(nsItem);
4396 cur = end;
4397 } while (*cur != 0);
4398 }
4399 return (ret);
4400}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004401
4402static int
4403xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4404 xmlSchemaTypePtr item,
4405 xmlNodePtr node,
4406 int minOccurs,
4407 int maxOccurs) {
4408
4409 if (maxOccurs != UNBOUNDED) {
4410 /*
4411 * TODO: Maby we should better not create the particle,
4412 * if min/max is invalid, since it could confuse the build of the
4413 * content model.
4414 */
4415 /*
4416 * 3.9.6 Schema Component Constraint: Particle Correct
4417 *
4418 */
4419 if (maxOccurs < 1) {
4420 /*
4421 * 2.2 {max occurs} must be greater than or equal to 1.
4422 */
4423 xmlSchemaPCustomAttrErr(ctxt,
4424 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4425 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4426 "The value must be greater than or equal to 1");
4427 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4428 } else if (minOccurs > maxOccurs) {
4429 /*
4430 * 2.1 {min occurs} must not be greater than {max occurs}.
4431 */
4432 xmlSchemaPCustomAttrErr(ctxt,
4433 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4434 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4435 "The value must not be greater than the value of 'maxOccurs'");
4436 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4437 }
4438 }
4439 return (0);
4440}
4441
Daniel Veillardc0826a72004-08-10 14:17:33 +00004442/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 * xmlSchemaParseAny:
4444 * @ctxt: a schema validation context
4445 * @schema: the schema being built
4446 * @node: a subtree containing XML Schema informations
4447 *
4448 * parse a XML schema Any declaration
4449 * *WARNING* this interface is highly subject to change
4450 *
4451 * Returns the new type structure or NULL in case of error
4452 */
4453static xmlSchemaTypePtr
4454xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4455 xmlNodePtr node)
4456{
4457 xmlSchemaTypePtr type;
4458 xmlNodePtr child = NULL;
4459 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004460 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004461 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004462
4463 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4464 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004465 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4466 "(nonNegativeInteger | unbounded)");
4467 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4468 "nonNegativeInteger");
4469 if ((minOccurs == 0) && (maxOccurs == 0))
4470 return (NULL);
4471
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004473 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004475 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004477 type->type = XML_SCHEMA_TYPE_ANY;
4478
Daniel Veillardc0826a72004-08-10 14:17:33 +00004479 wildc = xmlSchemaAddWildcard(ctxt);
4480 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004481 * Check min/max sanity.
4482 */
4483 type->maxOccurs = maxOccurs;
4484 type->minOccurs = minOccurs;
4485 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4486 node, type->minOccurs, type->maxOccurs);
4487 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004488 * This is not nice, since it is won't be used as a attribute wildcard,
4489 * but better than adding a field to the structure.
4490 */
4491 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004492 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004493 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004494 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004495 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4496 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004497 }
4498 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004499 xmlSchemaPErr2(ctxt, node, child,
4500 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4501 "Sequence %s has unexpected content\n", type->name,
4502 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004503 }
4504
4505 return (type);
4506}
4507
4508/**
4509 * xmlSchemaParseNotation:
4510 * @ctxt: a schema validation context
4511 * @schema: the schema being built
4512 * @node: a subtree containing XML Schema informations
4513 *
4514 * parse a XML schema Notation declaration
4515 *
4516 * Returns the new structure or NULL in case of error
4517 */
4518static xmlSchemaNotationPtr
4519xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004521{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004522 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 xmlSchemaNotationPtr ret;
4524 xmlNodePtr child = NULL;
4525
4526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4527 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004528 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004530 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4531 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 return (NULL);
4533 }
4534 ret = xmlSchemaAddNotation(ctxt, schema, name);
4535 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004536 return (NULL);
4537 }
4538 child = node->children;
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 }
4543 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004544 xmlSchemaPErr2(ctxt, node, child,
4545 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4546 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004547 }
4548
4549 return (ret);
4550}
4551
4552/**
4553 * xmlSchemaParseAnyAttribute:
4554 * @ctxt: a schema validation context
4555 * @schema: the schema being built
4556 * @node: a subtree containing XML Schema informations
4557 *
4558 * parse a XML schema AnyAttrribute declaration
4559 * *WARNING* this interface is highly subject to change
4560 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004561 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004562 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004563static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004564xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4565 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004566{
Daniel Veillard3646d642004-06-02 19:19:14 +00004567 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004569 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004570
4571 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4572 return (NULL);
4573
Daniel Veillard3646d642004-06-02 19:19:14 +00004574 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004575 if (ret == NULL) {
4576 return (NULL);
4577 }
William M. Bracke7091952004-05-11 15:09:58 +00004578 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004579 /*
4580 * Check for illegal attributes.
4581 */
4582 attr = node->properties;
4583 while (attr != NULL) {
4584 if (attr->ns == NULL) {
4585 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4586 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4587 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4588 xmlSchemaPIllegalAttrErr(ctxt,
4589 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4590 NULL, NULL, attr);
4591 }
4592 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4593 xmlSchemaPIllegalAttrErr(ctxt,
4594 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4595 NULL, NULL, attr);
4596 }
4597 attr = attr->next;
4598 }
4599 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4600 /*
4601 * Parse the namespace list.
4602 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004603 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4604 xmlSchemaFreeWildcard(ret);
4605 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004606 }
4607 /*
4608 * And now for the children...
4609 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004610 child = node->children;
4611 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004612 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4613 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004614 }
4615 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004616 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004617 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4618 NULL, NULL, node, child,
4619 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004620 }
4621
4622 return (ret);
4623}
4624
4625
4626/**
4627 * xmlSchemaParseAttribute:
4628 * @ctxt: a schema validation context
4629 * @schema: the schema being built
4630 * @node: a subtree containing XML Schema informations
4631 *
4632 * parse a XML schema Attrribute declaration
4633 * *WARNING* this interface is highly subject to change
4634 *
William M. Bracke7091952004-05-11 15:09:58 +00004635 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004636 */
4637static xmlSchemaAttributePtr
4638xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004639 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004640{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004641 const xmlChar *name, *attrValue;
4642 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004643 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004644 xmlNodePtr child = NULL;
4645 xmlAttrPtr attr, nameAttr;
4646 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004647
4648 /*
4649 * Note that the w3c spec assumes the schema to be validated with schema
4650 * for schemas beforehand.
4651 *
4652 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004653 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004654
4655 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4656 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004657 attr = xmlSchemaGetPropNode(node, "ref");
4658 nameAttr = xmlSchemaGetPropNode(node, "name");
4659
4660 if ((attr == NULL) && (nameAttr == NULL)) {
4661 /*
4662 * 3.2.3 : 3.1
4663 * One of ref or name must be present, but not both
4664 */
4665 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4666 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4667 "One of the attributes 'ref' or 'name' must be present");
4668 return (NULL);
4669 }
4670 if ((topLevel) || (attr == NULL)) {
4671 if (nameAttr == NULL) {
4672 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4673 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4674 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004675 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004676 }
4677 } else
4678 isRef = 1;
4679
4680 if (isRef) {
4681 char buf[100];
4682 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4683
4684 /*
4685 * Parse as attribute reference.
4686 */
4687 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4688 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4689 &refPrefix, &ref) != 0) {
4690 return (NULL);
4691 }
4692 snprintf(buf, 99, "#aRef %d", ctxt->counter++ + 1);
4693 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004694 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004695 if (ret == NULL) {
4696 if (repName != NULL)
4697 xmlFree(repName);
4698 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004699 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004700 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4701 ret->node = node;
4702 ret->refNs = refNs;
4703 ret->refPrefix = refPrefix;
4704 ret->ref = ref;
4705 /*
4706 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4707 */
4708 if (nameAttr != NULL)
4709 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4710 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4711 "ref", "name");
4712 /*
4713 * Check for illegal attributes.
4714 */
4715 attr = node->properties;
4716 while (attr != NULL) {
4717 if (attr->ns == NULL) {
4718 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4719 xmlStrEqual(attr->name, BAD_CAST "form")) {
4720 /*
4721 * 3.2.3 : 3.2
4722 * If ref is present, then all of <simpleType>,
4723 * form and type must be absent.
4724 */
4725 xmlSchemaPIllegalAttrErr(ctxt,
4726 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4727 (xmlSchemaTypePtr) ret, attr);
4728 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4729 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4730 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4731 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4732 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4733 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4734 xmlSchemaPIllegalAttrErr(ctxt,
4735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4736 &repName, (xmlSchemaTypePtr) ret, attr);
4737 }
4738 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4739 xmlSchemaPIllegalAttrErr(ctxt,
4740 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4741 &repName, (xmlSchemaTypePtr) ret, attr);
4742 }
4743 attr = attr->next;
4744 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004745 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004746 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004747
4748 /*
4749 * Parse as attribute declaration.
4750 */
4751 if (xmlSchemaPValAttrNode(ctxt,
4752 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4753 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4754 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004755 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004756 /*
4757 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4758 */
4759 /*
4760 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4761 */
4762 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4763 xmlSchemaPSimpleTypeErr(ctxt,
4764 XML_SCHEMAP_NO_XMLNS,
4765 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004766 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004767 "The value must not match 'xmlns'",
4768 NULL, NULL);
4769 if (repName != NULL)
4770 xmlFree(repName);
4771 return (NULL);
4772 }
4773 /*
4774 * Evaluate the target namespace
4775 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004776 if (topLevel) {
4777 ns = schema->targetNamespace;
4778 } else {
4779 attr = xmlSchemaGetPropNode(node, "form");
4780 if (attr != NULL) {
4781 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4782 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4783 ns = schema->targetNamespace;
4784 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4785 xmlSchemaPSimpleTypeErr(ctxt,
4786 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4787 &repName, NULL, (xmlNodePtr) attr,
4788 NULL, "(qualified | unqualified)",
4789 attrValue, NULL, NULL, NULL);
4790 }
4791 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4792 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004793 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004794 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004795 if (ret == NULL) {
4796 if (repName != NULL)
4797 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004798 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004799 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004800 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4801 ret->node = node;
4802 if (topLevel)
4803 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4804 /*
4805 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4806 */
4807 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4808 xmlSchemaPCustomErr(ctxt,
4809 XML_SCHEMAP_NO_XSI,
4810 &repName, (xmlSchemaTypePtr) ret, node,
4811 "The target namespace must not match '%s'",
4812 xmlSchemaInstanceNs);
4813 }
4814 /*
4815 * Check for illegal attributes.
4816 */
4817 attr = node->properties;
4818 while (attr != NULL) {
4819 if (attr->ns == NULL) {
4820 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4821 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4822 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4823 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4824 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4825 if ((topLevel) ||
4826 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4827 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4828 xmlSchemaPIllegalAttrErr(ctxt,
4829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4830 &repName, (xmlSchemaTypePtr) ret, attr);
4831 }
4832 }
4833 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4834 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4835 &repName, (xmlSchemaTypePtr) ret, attr);
4836 }
4837 attr = attr->next;
4838 }
4839 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4840 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004841 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004842 /* TODO: Check ID. */
4843 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004844 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004845 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004847 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4848 if (ret->defValue != NULL)
4849 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4850 /*
4851 * Attribute "default".
4852 */
4853 attr = xmlSchemaGetPropNode(node, "default");
4854 if (attr != NULL) {
4855 /*
4856 * 3.2.3 : 1
4857 * default and fixed must not both be present.
4858 */
4859 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4860 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4861 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4862 } else
4863 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4864 }
4865 if (topLevel == 0) {
4866 /*
4867 * Attribute "use".
4868 */
4869 attr = xmlSchemaGetPropNode(node, "use");
4870 if (attr != NULL) {
4871 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4872 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4873 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4874 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4875 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4876 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4877 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4878 else
4879 xmlSchemaPSimpleTypeErr(ctxt,
4880 XML_SCHEMAP_INVALID_ATTR_USE,
4881 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004882 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004883 attrValue, NULL, NULL, NULL);
4884 } else
4885 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4886 /*
4887 * 3.2.3 : 2
4888 * If default and use are both present, use must have
4889 * the actual value optional.
4890 */
4891 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4892 (ret->defValue != NULL) &&
4893 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4894 xmlSchemaPSimpleTypeErr(ctxt,
4895 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4896 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004897 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004898 "The value must be 'optional' if the attribute "
4899 "'default' is present as well", NULL, NULL);
4900 }
4901 }
4902 /*
4903 * And now for the children...
4904 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004905 child = node->children;
4906 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004907 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4908 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004909 }
4910 if (isRef) {
4911 if (child != NULL) {
4912 if (IS_SCHEMA(child, "simpleType"))
4913 /*
4914 * 3.2.3 : 3.2
4915 * If ref is present, then all of <simpleType>,
4916 * form and type must be absent.
4917 */
4918 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4919 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4920 "(annotation?)");
4921 else
4922 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4923 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4924 "(annotation?)");
4925 }
4926 } else {
4927 if (IS_SCHEMA(child, "simpleType")) {
4928 if (ret->typeName != NULL) {
4929 /*
4930 * 3.2.3 : 4
4931 * type and <simpleType> must not both be present.
4932 */
4933 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4934 &repName, (xmlSchemaTypePtr) ret, node, child,
4935 "The attribute 'type' and the <simpleType> child "
4936 "are mutually exclusive", NULL);
4937 } else
4938 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4939 child = child->next;
4940 }
4941 if (child != NULL)
4942 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4943 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4944 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004946 /*
4947 * Cleanup.
4948 */
4949 if (repName != NULL)
4950 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004951 return (ret);
4952}
4953
4954/**
4955 * xmlSchemaParseAttributeGroup:
4956 * @ctxt: a schema validation context
4957 * @schema: the schema being built
4958 * @node: a subtree containing XML Schema informations
4959 *
4960 * parse a XML schema Attribute Group declaration
4961 * *WARNING* this interface is highly subject to change
4962 *
4963 * Returns the attribute group or NULL in case of error.
4964 */
4965static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004966xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004967 xmlSchemaPtr schema, xmlNodePtr node,
4968 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004969{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004970 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004971 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004972 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004973 const xmlChar *oldcontainer;
4974 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004975
4976 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4977 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004978
4979 nameAttr = xmlSchemaGetPropNode(node, "name");
4980 attr = xmlSchemaGetPropNode(node, "ref");
4981 if ((topLevel) || (attr == NULL)) {
4982 /*
4983 * Parse as an attribute group definition.
4984 * Note that those are allowed at top level only.
4985 */
4986 if (nameAttr == NULL) {
4987 xmlSchemaPMissingAttrErr(ctxt,
4988 XML_SCHEMAP_S4S_ATTR_MISSING,
4989 NULL, NULL, node, "name", NULL);
4990 return (NULL);
4991 }
4992 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
4993 /*
4994 * The name is crucial, exit if invalid.
4995 */
4996 if (xmlSchemaPValAttrNode(ctxt,
4997 NULL, NULL, nameAttr,
4998 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4999 return (NULL);
5000 }
5001 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5002 if (ret == NULL)
5003 return (NULL);
5004 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5005 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5006 ret->node = node;
5007 } else {
5008 char buf[50];
5009 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5010
5011 /*
5012 * Parse as an attribute group definition reference.
5013 */
5014 if (attr == NULL) {
5015 xmlSchemaPMissingAttrErr(ctxt,
5016 XML_SCHEMAP_S4S_ATTR_MISSING,
5017 NULL, NULL, node, "ref", NULL);
5018 }
5019 xmlSchemaPValAttrNodeQName(ctxt, schema,
5020 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5021
5022 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5023 name = (const xmlChar *) buf;
5024 if (name == NULL) {
5025 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5026 "attribute group definition reference", node);
5027 return (NULL);
5028 }
5029 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5030 if (ret == NULL)
5031 return (NULL);
5032 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5033 ret->ref = ref;
5034 ret->refNs = refNs;
5035 /* TODO: Is @refPrefix currently used? */
5036 ret->refPrefix = refPrefix;
5037 ret->node = node;
5038 }
5039 /*
5040 * Check for illegal attributes.
5041 */
5042 attr = node->properties;
5043 while (attr != NULL) {
5044 if (attr->ns == NULL) {
5045 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5046 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5047 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5048 {
5049 xmlSchemaPIllegalAttrErr(ctxt,
5050 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5051 NULL, NULL, attr);
5052 }
5053 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5054 xmlSchemaPIllegalAttrErr(ctxt,
5055 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5056 NULL, NULL, attr);
5057 }
5058 attr = attr->next;
5059 }
5060 /* TODO: Validate "id" ? */
5061 /*
5062 * And now for the children...
5063 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005064 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005065 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005066 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005067 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5069 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005070 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005071 if (topLevel) {
5072 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5073 if (IS_SCHEMA(child, "anyAttribute")) {
5074 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5075 child = child->next;
5076 }
5077 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005078 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005079 xmlSchemaPContentErr(ctxt,
5080 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5081 NULL, NULL, node, child, NULL,
5082 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005084 ctxt->container = oldcontainer;
5085 return (ret);
5086}
5087
5088/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005089 * xmlSchemaPValAttrFormDefault:
5090 * @value: the value
5091 * @flags: the flags to be modified
5092 * @flagQualified: the specific flag for "qualified"
5093 *
5094 * Returns 0 if the value is valid, 1 otherwise.
5095 */
5096static int
5097xmlSchemaPValAttrFormDefault(const xmlChar *value,
5098 int *flags,
5099 int flagQualified)
5100{
5101 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5102 if ((*flags & flagQualified) == 0)
5103 *flags |= flagQualified;
5104 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5105 return (1);
5106
5107 return (0);
5108}
5109
5110/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005111 * xmlSchemaPValAttrBlockFinal:
5112 * @value: the value
5113 * @flags: the flags to be modified
5114 * @flagAll: the specific flag for "#all"
5115 * @flagExtension: the specific flag for "extension"
5116 * @flagRestriction: the specific flag for "restriction"
5117 * @flagSubstitution: the specific flag for "substitution"
5118 * @flagList: the specific flag for "list"
5119 * @flagUnion: the specific flag for "union"
5120 *
5121 * Validates the value of the attribute "final" and "block". The value
5122 * is converted into the specified flag values and returned in @flags.
5123 *
5124 * Returns 0 if the value is valid, 1 otherwise.
5125 */
5126
5127static int
5128xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5129 int *flags,
5130 int flagAll,
5131 int flagExtension,
5132 int flagRestriction,
5133 int flagSubstitution,
5134 int flagList,
5135 int flagUnion)
5136{
5137 int ret = 0;
5138
5139 /*
5140 * TODO: This does not check for dublicate entries.
5141 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005142 if (value == NULL)
5143 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005144 if (xmlStrEqual(value, BAD_CAST "#all")) {
5145 if (flagAll != -1)
5146 *flags |= flagAll;
5147 else {
5148 if (flagExtension != -1)
5149 *flags |= flagExtension;
5150 if (flagRestriction != -1)
5151 *flags |= flagRestriction;
5152 if (flagSubstitution != -1)
5153 *flags |= flagSubstitution;
5154 if (flagList != -1)
5155 *flags |= flagList;
5156 if (flagUnion != -1)
5157 *flags |= flagUnion;
5158 }
5159 } else {
5160 const xmlChar *end, *cur = value;
5161 xmlChar *item;
5162
5163 do {
5164 while (IS_BLANK_CH(*cur))
5165 cur++;
5166 end = cur;
5167 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5168 end++;
5169 if (end == cur)
5170 break;
5171 item = xmlStrndup(cur, end - cur);
5172 if (xmlStrEqual(item, BAD_CAST "extension")) {
5173 if (flagExtension != -1) {
5174 if ((*flags & flagExtension) == 0)
5175 *flags |= flagExtension;
5176 } else
5177 ret = 1;
5178 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5179 if (flagRestriction != -1) {
5180 if ((*flags & flagRestriction) == 0)
5181 *flags |= flagRestriction;
5182 } else
5183 ret = 1;
5184 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5185 if (flagSubstitution != -1) {
5186 if ((*flags & flagSubstitution) == 0)
5187 *flags |= flagSubstitution;
5188 } else
5189 ret = 1;
5190 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5191 if (flagList != -1) {
5192 if ((*flags & flagList) == 0)
5193 *flags |= flagList;
5194 } else
5195 ret = 1;
5196 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5197 if (flagUnion != -1) {
5198 if ((*flags & flagUnion) == 0)
5199 *flags |= flagUnion;
5200 } else
5201 ret = 1;
5202 } else
5203 ret = 1;
5204 if (item != NULL)
5205 xmlFree(item);
5206 cur = end;
5207 } while ((ret == 0) && (*cur != 0));
5208 }
5209
5210 return (ret);
5211}
5212
5213/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005214 * xmlSchemaParseElement:
5215 * @ctxt: a schema validation context
5216 * @schema: the schema being built
5217 * @node: a subtree containing XML Schema informations
5218 *
5219 * parse a XML schema Element declaration
5220 * *WARNING* this interface is highly subject to change
5221 *
William M. Bracke7091952004-05-11 15:09:58 +00005222 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005223 */
5224static xmlSchemaElementPtr
5225xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005226 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005227{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005228 const xmlChar *name = NULL;
5229 const xmlChar *attrValue;
5230 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 xmlSchemaElementPtr ret;
5232 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005233 const xmlChar *oldcontainer;
5234 xmlAttrPtr attr, nameAttr;
5235 int minOccurs, maxOccurs;
5236 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005237
5238 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5239 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005240
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5242 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005243
Daniel Veillardc0826a72004-08-10 14:17:33 +00005244 oldcontainer = ctxt->container;
5245
5246 nameAttr = xmlSchemaGetPropNode(node, "name");
5247 attr = xmlSchemaGetPropNode(node, "ref");
5248 if ((topLevel) || (attr == NULL)) {
5249 if (nameAttr == NULL) {
5250 xmlSchemaPMissingAttrErr(ctxt,
5251 XML_SCHEMAP_S4S_ATTR_MISSING,
5252 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5253 "name", NULL);
5254 return (NULL);
5255 }
5256 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5257 } else {
5258 isRef = 1;
5259
5260 }
5261 /*
5262 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5263 * to no component at all
5264 * TODO: It might be better to validate the element, even if it won't be
5265 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 */
5267 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5268 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005269 if ((minOccurs == 0) && (maxOccurs == 0))
5270 return (NULL);
5271 /*
5272 * If we get a "ref" attribute on a local <element> we will assume it's
5273 * a reference - even if there's a "name" attribute; this seems to be more
5274 * robust.
5275 */
5276 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005277 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005278 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5279
5280 /*
5281 * Parse as a particle.
5282 */
5283 xmlSchemaPValAttrNodeQName(ctxt, schema,
5284 (xmlChar **) &xmlSchemaElemDesAttrRef,
5285 NULL, attr, &refNs, &refPrefix, &ref);
5286
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005287 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005288 name = (const xmlChar *) buf;
5289 ret = xmlSchemaAddElement(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005290 if (ret == NULL) {
5291 if (repName != NULL)
5292 xmlFree(repName);
5293 return (NULL);
5294 }
5295 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5296 ret->node = node;
5297 ret->ref = ref;
5298 ret->refNs = refNs;
5299 ret->refPrefix = refPrefix;
5300 ret->flags |= XML_SCHEMAS_ELEM_REF;
5301 /*
5302 * Check for illegal attributes.
5303 */
5304 /*
5305 * 3.3.3 : 2.1
5306 * One of ref or name must be present, but not both
5307 */
5308 if (nameAttr != NULL) {
5309 xmlSchemaPMutualExclAttrErr(ctxt,
5310 XML_SCHEMAP_SRC_ELEMENT_2_1,
5311 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5312 "ref", "name");
5313 }
5314 /* 3.3.3 : 2.2 */
5315 attr = node->properties;
5316 while (attr != NULL) {
5317 if (attr->ns == NULL) {
5318 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5319 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5320 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5321 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5322 (!xmlStrEqual(attr->name, BAD_CAST "name"))) {
5323 xmlSchemaPCustomAttrErr(ctxt,
5324 XML_SCHEMAP_SRC_ELEMENT_2_2,
5325 &repName, (xmlSchemaTypePtr) ret, attr,
5326 "Only the attributes 'minOccurs', 'maxOccurs' and "
5327 "'id' are allowed in addition to 'ref'");
5328 break;
5329 }
5330 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5331 xmlSchemaPIllegalAttrErr(ctxt,
5332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5333 &repName, (xmlSchemaTypePtr) ret, attr);
5334 }
5335 attr = attr->next;
5336 }
5337 } else {
5338 const xmlChar *ns = NULL, *fixed;
5339
5340 /*
5341 * Parse as an element declaration.
5342 */
5343 if (xmlSchemaPValAttrNode(ctxt,
5344 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5345 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5346 return (NULL);
5347 /*
5348 * Evaluate the target namespace.
5349 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005350 if (topLevel) {
5351 ns = schema->targetNamespace;
5352 } else {
5353 attr = xmlSchemaGetPropNode(node, "form");
5354 if (attr != NULL) {
5355 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5356 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005357 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005358 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5359 xmlSchemaPSimpleTypeErr(ctxt,
5360 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5361 &repName, NULL, (xmlNodePtr) attr,
5362 NULL, "(qualified | unqualified)",
5363 attrValue, NULL, NULL, NULL);
5364 }
5365 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5366 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005367 }
5368 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005369 if (ret == NULL) {
5370 if (repName != NULL)
5371 xmlFree(repName);
5372 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005373 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005374 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5375 ret->node = node;
5376 /*
5377 * Check for illegal attributes.
5378 */
William M. Bracke7091952004-05-11 15:09:58 +00005379 attr = node->properties;
5380 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005381 if (attr->ns == NULL) {
5382 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5383 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5384 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5385 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5386 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5387 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
5388 (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) {
5389 if (topLevel == 0) {
5390 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5391 /*
5392 * 3.3.6 : 3 If there is a non-·absent· {substitution
5393 * group affiliation}, then {scope} must be global.
5394 * TODO: This one is redundant, since the S4S does
5395 * prohibit this attribute on local declarations already;
5396 * so why an explicit error code? Weird spec.
William M. Brack2f2a6632004-08-20 23:09:47 +00005397 * TODO: Move this to the proper constraint layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005398 */
5399 xmlSchemaPIllegalAttrErr(ctxt,
5400 XML_SCHEMAP_E_PROPS_CORRECT_3,
5401 &repName, (xmlSchemaTypePtr) ret, attr);
5402 } else if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
5403 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
5404 (!xmlStrEqual(attr->name, BAD_CAST "form"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005405
Daniel Veillardc0826a72004-08-10 14:17:33 +00005406 xmlSchemaPIllegalAttrErr(ctxt,
5407 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5408 &repName, (xmlSchemaTypePtr) ret, attr);
5409 }
5410 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5411 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5412 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5413
5414 xmlSchemaPIllegalAttrErr(ctxt,
5415 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5416 &repName, (xmlSchemaTypePtr) ret, attr);
5417 }
5418 }
5419 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5420
5421 xmlSchemaPIllegalAttrErr(ctxt,
5422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5423 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005424 }
5425 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005426 }
William M. Bracke7091952004-05-11 15:09:58 +00005427 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005428 * Extract/validate attributes.
5429 */
5430 if (topLevel) {
5431 /*
5432 * Process top attributes of global element declarations here.
5433 */
5434 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5435 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5436 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5437 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5438 &(ret->substGroupNs), NULL, &(ret->substGroup));
5439 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5440 node, "abstract", 0))
5441 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5442 /*
5443 * Attribute "final".
5444 */
5445 attr = xmlSchemaGetPropNode(node, "final");
5446 if (attr == NULL) {
5447 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5448 } else {
5449 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5450 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5451 -1,
5452 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5453 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5454 xmlSchemaPSimpleTypeErr(ctxt,
5455 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5456 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005457 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005458 attrValue, NULL, NULL, NULL);
5459 }
5460 }
5461 }
5462 /*
5463 * Attribute "block".
5464 */
5465 attr = xmlSchemaGetPropNode(node, "block");
5466 if (attr == NULL) {
5467 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5468 } else {
5469 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5470 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5471 -1,
5472 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5473 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5474 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5475 xmlSchemaPSimpleTypeErr(ctxt,
5476 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5477 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005478 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005479 "restriction | substitution))", attrValue,
5480 NULL, NULL, NULL);
5481 }
5482 }
5483 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5484 node, "nillable", 0))
5485 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005486
Daniel Veillardc0826a72004-08-10 14:17:33 +00005487 xmlSchemaPValAttrQName(ctxt, schema,
5488 &repName, (xmlSchemaTypePtr) ret, node,
5489 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005490
Daniel Veillardc0826a72004-08-10 14:17:33 +00005491 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5492 attr = xmlSchemaGetPropNode(node, "fixed");
5493 if (attr != NULL) {
5494 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5495 if (ret->value != NULL) {
5496 /*
5497 * 3.3.3 : 1
5498 * default and fixed must not both be present.
5499 */
5500 xmlSchemaPMutualExclAttrErr(ctxt,
5501 XML_SCHEMAP_SRC_ELEMENT_1,
5502 &repName, (xmlSchemaTypePtr) ret, attr,
5503 "default", "fixed");
5504 } else {
5505 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5506 ret->value = fixed;
5507 }
5508 }
5509 }
5510 /*
5511 * Extract/validate common attributes.
5512 */
5513 /* TODO: Check ID: */
5514 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5515 ret->minOccurs = minOccurs;
5516 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005517 if (topLevel != 1)
5518 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5519 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005520 /*
5521 * And now for the children...
5522 */
5523 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005524 child = node->children;
5525 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005526 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5527 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005529 if (isRef) {
5530 if (child != NULL) {
5531 xmlSchemaPContentErr(ctxt,
5532 XML_SCHEMAP_SRC_ELEMENT_2_2,
5533 &repName, (xmlSchemaTypePtr) ret, node, child,
5534 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005535 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005537 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005538 /*
5539 * 3.3.3 : 3
5540 * "type" and either <simpleType> or <complexType> are mutually
5541 * exclusive
5542 */
William M. Bracke7091952004-05-11 15:09:58 +00005543 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 xmlSchemaPContentErr(ctxt,
5545 XML_SCHEMAP_SRC_ELEMENT_3,
5546 &repName, (xmlSchemaTypePtr) ret, node, child,
5547 "The attribute 'type' and the <complexType> child are "
5548 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005549 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005550 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005551 child = child->next;
5552 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005553 /*
5554 * 3.3.3 : 3
5555 * "type" and either <simpleType> or <complexType> are
5556 * mutually exclusive
5557 */
William M. Bracke7091952004-05-11 15:09:58 +00005558 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005559 xmlSchemaPContentErr(ctxt,
5560 XML_SCHEMAP_SRC_ELEMENT_3,
5561 &repName, (xmlSchemaTypePtr) ret, node, child,
5562 "The attribute 'type' and the <simpleType> child are "
5563 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005564 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005565 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005566 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005567 }
William M. Bracke7091952004-05-11 15:09:58 +00005568 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
William M. Bracke7091952004-05-11 15:09:58 +00005570 TODO child = child->next;
5571 }
5572 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 xmlSchemaPContentErr(ctxt,
5574 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5575 &repName, (xmlSchemaTypePtr) ret, node, child,
5576 NULL, "(annotation?, ((simpleType | complexType)?, "
5577 "(unique | key | keyref)*))");
5578 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005579
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005581 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005582 /*
5583 * Cleanup.
5584 */
5585 if (repName != NULL)
5586 xmlFree(repName);
5587 /*
5588 * NOTE: Element Declaration Representation OK 4. will be checked at a
5589 * different layer.
5590 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005591 return (ret);
5592}
5593
5594/**
5595 * xmlSchemaParseUnion:
5596 * @ctxt: a schema validation context
5597 * @schema: the schema being built
5598 * @node: a subtree containing XML Schema informations
5599 *
5600 * parse a XML schema Union definition
5601 * *WARNING* this interface is highly subject to change
5602 *
William M. Bracke7091952004-05-11 15:09:58 +00005603 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005604 * 1 in case of success.
5605 */
5606static xmlSchemaTypePtr
5607xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005608 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005609{
5610 xmlSchemaTypePtr type, subtype, last = NULL;
5611 xmlNodePtr child = NULL;
5612 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005613 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005614
5615 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5616 return (NULL);
5617
William M. Brack2f2a6632004-08-20 23:09:47 +00005618 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5619 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005620 if (type == NULL)
5621 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005622 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005623 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005624 /*
5625 * Check for illegal attributes.
5626 */
5627 attr = node->properties;
5628 while (attr != NULL) {
5629 if (attr->ns == NULL) {
5630 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5631 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5632 xmlSchemaPIllegalAttrErr(ctxt,
5633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5634 NULL, type, attr);
5635 }
5636 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5637 xmlSchemaPIllegalAttrErr(ctxt,
5638 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5639 NULL, type, attr);
5640 }
5641 attr = attr->next;
5642 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005643 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005644 /*
5645 * Attribute "memberTypes". This is a list of QNames.
5646 * TODO: Validate the QNames.
5647 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005648 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005649 /*
5650 * And now for the children...
5651 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005652 child = node->children;
5653 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005654 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5655 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005656 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005657 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005659 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005660 if (subtype != NULL) {
5661 if (last == NULL) {
5662 type->subtypes = subtype;
5663 last = subtype;
5664 } else {
5665 last->next = subtype;
5666 last = subtype;
5667 }
5668 last->next = NULL;
5669 }
5670 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 }
5672 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005673 /* TODO: Think about the error code. */
5674 xmlSchemaPContentErr(ctxt,
5675 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5676 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005677 }
5678 return (type);
5679}
5680
5681/**
5682 * xmlSchemaParseList:
5683 * @ctxt: a schema validation context
5684 * @schema: the schema being built
5685 * @node: a subtree containing XML Schema informations
5686 *
5687 * parse a XML schema List definition
5688 * *WARNING* this interface is highly subject to change
5689 *
William M. Bracke7091952004-05-11 15:09:58 +00005690 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005691 * 1 in case of success.
5692 */
5693static xmlSchemaTypePtr
5694xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005695 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005696{
5697 xmlSchemaTypePtr type, subtype;
5698 xmlNodePtr child = NULL;
5699 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005700 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005701
5702 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5703 return (NULL);
5704
William M. Brack2f2a6632004-08-20 23:09:47 +00005705 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5706 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005707 if (type == NULL)
5708 return (NULL);
5709 type->node = node;
5710 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005711 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005712 /*
5713 * Check for illegal attributes.
5714 */
5715 attr = node->properties;
5716 while (attr != NULL) {
5717 if (attr->ns == NULL) {
5718 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5719 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5720 xmlSchemaPIllegalAttrErr(ctxt,
5721 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5722 NULL, type, attr);
5723 }
5724 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5725 xmlSchemaPIllegalAttrErr(ctxt,
5726 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5727 NULL, type, attr);
5728 }
5729 attr = attr->next;
5730 }
5731 /*
5732 * Attribute "itemType".
5733 */
5734 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5735 node, "itemType", &(type->baseNs), NULL, &(type->base));
5736 /*
5737 * And now for the children...
5738 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005739 child = node->children;
5740 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5742 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005743 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005744 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005745 if (IS_SCHEMA(child, "simpleType")) {
5746 if (type->base != NULL) {
5747 xmlSchemaPCustomErr(ctxt,
5748 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5749 NULL, type, node,
5750 "The attribute 'itemType' and the <simpleType> child "
5751 "are mutually exclusive", NULL);
5752 } else {
5753 subtype = (xmlSchemaTypePtr)
5754 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5755 type->subtypes = subtype;
5756 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005757 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005758 }
5759 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005760 /* TODO: Think about the error code. */
5761 xmlSchemaPContentErr(ctxt,
5762 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5763 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005764 }
5765 return (type);
5766}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005767
Daniel Veillard4255d502002-04-16 15:50:10 +00005768/**
5769 * xmlSchemaParseSimpleType:
5770 * @ctxt: a schema validation context
5771 * @schema: the schema being built
5772 * @node: a subtree containing XML Schema informations
5773 *
5774 * parse a XML schema Simple Type definition
5775 * *WARNING* this interface is highly subject to change
5776 *
William M. Bracke7091952004-05-11 15:09:58 +00005777 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005778 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005779 */
5780static xmlSchemaTypePtr
5781xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005782 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005783{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005784 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00005785 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005786 const xmlChar *attrValue = NULL;
5787 xmlChar *repName = NULL;
5788 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005789
5790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5791 return (NULL);
5792
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005794
Daniel Veillardc0826a72004-08-10 14:17:33 +00005795 if (topLevel) {
5796 if (attr == NULL) {
5797 xmlSchemaPMissingAttrErr(ctxt,
5798 XML_SCHEMAP_S4S_ATTR_MISSING,
5799 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5800 "name", NULL);
5801 return (NULL);
5802 } else if (xmlSchemaPValAttrNode(ctxt,
5803 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, attr,
5804 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005805 return (NULL);
5806 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005807 }
5808
5809 if (topLevel == 0) {
5810 char buf[100];
5811
Daniel Veillard01fa6152004-06-29 17:04:39 +00005812 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005813 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005814 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 snprintf(buf, 99, "#st %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005816 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 if (type == NULL)
5818 return (NULL);
5819 type->node = node;
5820 type->type = XML_SCHEMA_TYPE_SIMPLE;
5821 /*
5822 * Check for illegal attributes.
5823 */
5824 attr = node->properties;
5825 while (attr != NULL) {
5826 if (attr->ns == NULL) {
5827 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5828 xmlSchemaPIllegalAttrErr(ctxt,
5829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5830 &repName, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005831 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005832 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5833 xmlSchemaPIllegalAttrErr(ctxt,
5834 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5835 &repName, type, attr);
5836 }
5837 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005838 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005839 } else {
5840 /*
5841 * Parse as global simple type definition.
5842 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005843 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844 if (type == NULL)
5845 return (NULL);
5846 type->node = node;
5847 type->type = XML_SCHEMA_TYPE_SIMPLE;
5848 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5849 /*
5850 * Check for illegal attributes.
5851 */
5852 attr = node->properties;
5853 while (attr != NULL) {
5854 if (attr->ns == NULL) {
5855 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5856 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5857 (!xmlStrEqual(attr->name, BAD_CAST "final"))){
5858 xmlSchemaPIllegalAttrErr(ctxt,
5859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5860 &repName, type, attr);
5861 }
5862 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5863 xmlSchemaPIllegalAttrErr(ctxt,
5864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5865 &repName, type, attr);
5866 }
5867 attr = attr->next;
5868 }
5869 /*
5870 * Attribute "final".
5871 */
5872 attr = xmlSchemaGetPropNode(node, "final");
5873 if (attr == NULL) {
5874 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5875 } else {
5876 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5877 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5878 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5879 XML_SCHEMAS_TYPE_FINAL_LIST,
5880 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5881
5882 xmlSchemaPSimpleTypeErr(ctxt,
5883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5884 &repName, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005885 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005886 attrValue, NULL, NULL, NULL);
5887 }
5888 }
5889 }
5890 /* TODO: Check id. */
5891 type->id = xmlSchemaGetProp(ctxt, node, "id");
5892 /*
5893 * And now for the children...
5894 */
5895 ctxtType = ctxt->ctxtType;
5896 ctxt->ctxtType = type;
5897 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005898 child = node->children;
5899 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005900 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5901 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005902 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005904 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005905 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005906 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005907 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005908 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005909 subtype = (xmlSchemaTypePtr)
5910 xmlSchemaParseList(ctxt, schema, child);
5911 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005912 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005913 subtype = (xmlSchemaTypePtr)
5914 xmlSchemaParseUnion(ctxt, schema, child);
5915 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005916 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 type->subtypes = subtype;
5918 if ((child != NULL) || (subtype == NULL)) {
5919 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5920 &repName, type, node, child, NULL,
5921 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005922 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005923 ctxt->ctxtType = ctxtType;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 if (repName != NULL)
5925 xmlFree(repName);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005926
Daniel Veillard4255d502002-04-16 15:50:10 +00005927 return (type);
5928}
5929
5930
5931/**
5932 * xmlSchemaParseGroup:
5933 * @ctxt: a schema validation context
5934 * @schema: the schema being built
5935 * @node: a subtree containing XML Schema informations
5936 *
5937 * parse a XML schema Group definition
5938 * *WARNING* this interface is highly subject to change
5939 *
William M. Bracke7091952004-05-11 15:09:58 +00005940 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005941 * 1 in case of success.
5942 */
5943static xmlSchemaTypePtr
5944xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005945 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005946{
5947 xmlSchemaTypePtr type, subtype;
5948 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005949 const xmlChar *name;
5950 const xmlChar *ref = NULL, *refNs = NULL;
5951 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005952 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005953
5954 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5955 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005956 /*
5957 * TODO: Validate the element even if no item is created
5958 * (i.e. min/maxOccurs == 0).
5959 */
5960 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5961 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
5962 if ((minOccurs == 0) && (maxOccurs == 0)) {
5963 return (NULL);
5964 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005965 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005966 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005967 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
5968 if (ref == NULL) {
5969 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005970 XML_SCHEMAP_GROUP_NONAME_NOREF,
5971 "Group definition or particle: One of the attributes \"name\" "
5972 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005973 return (NULL);
5974 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005975 if (refNs == NULL)
5976 refNs = schema->targetNamespace;
5977 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
5978 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00005979 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005980 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005981 if (type == NULL)
5982 return (NULL);
5983 type->node = node;
5984 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00005985 if (topLevel)
5986 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005987 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 type->ref = ref;
5989 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005990 type->minOccurs = minOccurs;
5991 type->maxOccurs = maxOccurs;
5992 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005993 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00005994
5995 child = node->children;
5996 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005997 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5998 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 }
6000 subtype = NULL;
6001 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006002 subtype = (xmlSchemaTypePtr)
6003 xmlSchemaParseAll(ctxt, schema, child);
6004 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006005 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006006 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6007 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006008 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006009 subtype = (xmlSchemaTypePtr)
6010 xmlSchemaParseSequence(ctxt, schema, child);
6011 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006012 }
6013 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006014 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006015 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006016 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006017 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006018 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 }
6020
6021 return (type);
6022}
6023
6024/**
6025 * xmlSchemaParseAll:
6026 * @ctxt: a schema validation context
6027 * @schema: the schema being built
6028 * @node: a subtree containing XML Schema informations
6029 *
6030 * parse a XML schema All definition
6031 * *WARNING* this interface is highly subject to change
6032 *
William M. Bracke7091952004-05-11 15:09:58 +00006033 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006034 * 1 in case of success.
6035 */
6036static xmlSchemaTypePtr
6037xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006039{
6040 xmlSchemaTypePtr type, subtype, last = NULL;
6041 xmlNodePtr child = NULL;
6042 xmlChar name[30];
6043
6044 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6045 return (NULL);
6046
6047
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006049 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 if (type == NULL)
6051 return (NULL);
6052 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006053 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006054 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006055
6056 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6057 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Daniel Veillard4255d502002-04-16 15:50:10 +00006058
6059 child = node->children;
6060 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006061 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6062 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006063 }
6064 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006065 subtype = (xmlSchemaTypePtr)
6066 xmlSchemaParseElement(ctxt, schema, child, 0);
6067 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006068 if (subtype->minOccurs > 1)
6069 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006070 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006071 NULL, NULL);
6072 if (subtype->maxOccurs > 1)
6073 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006074 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006075 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006076 if (last == NULL) {
6077 type->subtypes = subtype;
6078 last = subtype;
6079 } else {
6080 last->next = subtype;
6081 last = subtype;
6082 }
6083 last->next = NULL;
6084 }
6085 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006086 }
6087 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006089 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006090 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 }
6092
6093 return (type);
6094}
6095
6096/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006097 * xmlSchemaCleanupDoc:
6098 * @ctxt: a schema validation context
6099 * @node: the root of the document.
6100 *
6101 * removes unwanted nodes in a schemas document tree
6102 */
6103static void
6104xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6105{
6106 xmlNodePtr delete, cur;
6107
6108 if ((ctxt == NULL) || (root == NULL)) return;
6109
6110 /*
6111 * Remove all the blank text nodes
6112 */
6113 delete = NULL;
6114 cur = root;
6115 while (cur != NULL) {
6116 if (delete != NULL) {
6117 xmlUnlinkNode(delete);
6118 xmlFreeNode(delete);
6119 delete = NULL;
6120 }
6121 if (cur->type == XML_TEXT_NODE) {
6122 if (IS_BLANK_NODE(cur)) {
6123 if (xmlNodeGetSpacePreserve(cur) != 1) {
6124 delete = cur;
6125 }
6126 }
6127 } else if ((cur->type != XML_ELEMENT_NODE) &&
6128 (cur->type != XML_CDATA_SECTION_NODE)) {
6129 delete = cur;
6130 goto skip_children;
6131 }
6132
6133 /*
6134 * Skip to next node
6135 */
6136 if (cur->children != NULL) {
6137 if ((cur->children->type != XML_ENTITY_DECL) &&
6138 (cur->children->type != XML_ENTITY_REF_NODE) &&
6139 (cur->children->type != XML_ENTITY_NODE)) {
6140 cur = cur->children;
6141 continue;
6142 }
6143 }
6144 skip_children:
6145 if (cur->next != NULL) {
6146 cur = cur->next;
6147 continue;
6148 }
6149
6150 do {
6151 cur = cur->parent;
6152 if (cur == NULL)
6153 break;
6154 if (cur == root) {
6155 cur = NULL;
6156 break;
6157 }
6158 if (cur->next != NULL) {
6159 cur = cur->next;
6160 break;
6161 }
6162 } while (cur != NULL);
6163 }
6164 if (delete != NULL) {
6165 xmlUnlinkNode(delete);
6166 xmlFreeNode(delete);
6167 delete = NULL;
6168 }
6169}
6170
William M. Brack2f2a6632004-08-20 23:09:47 +00006171
6172/**
6173 * xmlSchemaImportSchema
6174 *
6175 * @ctxt: a schema validation context
6176 * @schemaLocation: an URI defining where to find the imported schema
6177 *
6178 * import a XML schema
6179 * *WARNING* this interface is highly subject to change
6180 *
6181 * Returns -1 in case of error and 1 in case of success.
6182 */
6183#if 0
6184static xmlSchemaImportPtr
6185xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6186 const xmlChar *schemaLocation)
6187{
6188 xmlSchemaImportPtr import;
6189 xmlSchemaParserCtxtPtr newctxt;
6190
6191 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6192 if (newctxt == NULL) {
6193 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6194 NULL);
6195 return (NULL);
6196 }
6197 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6198 /* Keep the same dictionnary for parsing, really */
6199 xmlDictReference(ctxt->dict);
6200 newctxt->dict = ctxt->dict;
6201 newctxt->includes = 0;
6202 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6203
6204 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6205 ctxt->userData);
6206
6207 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6208 if (import == NULL) {
6209 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6210 NULL);
6211 xmlSchemaFreeParserCtxt(newctxt);
6212 return (NULL);
6213 }
6214
6215 memset(import, 0, sizeof(xmlSchemaImport));
6216 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6217 import->schema = xmlSchemaParse(newctxt);
6218
6219 if (import->schema == NULL) {
6220 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006221 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006222 "Failed to import schema from location \"%s\".\n",
6223 schemaLocation, NULL);
6224
6225 xmlSchemaFreeParserCtxt(newctxt);
6226 /* The schemaLocation is held by the dictionary.
6227 if (import->schemaLocation != NULL)
6228 xmlFree((xmlChar *)import->schemaLocation);
6229 */
6230 xmlFree(import);
6231 return NULL;
6232 }
6233
6234 xmlSchemaFreeParserCtxt(newctxt);
6235 return import;
6236}
6237#endif
6238
6239static void
6240xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6241{
6242 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6243 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6244
6245 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6246 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6247
6248 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6249 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6250 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6251 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6252 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6253 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6254 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6255 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6256
6257 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6258 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6259 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6260 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6261 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6262 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6263}
6264
6265static void
6266xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6267 xmlSchemaPtr schema,
6268 xmlNodePtr node)
6269{
6270 xmlAttrPtr attr;
6271 const xmlChar *val;
6272
6273 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6274 if (attr != NULL) {
6275 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6276 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6277 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6278 xmlSchemaPSimpleTypeErr(ctxt,
6279 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6280 NULL, NULL, (xmlNodePtr) attr, NULL,
6281 "(qualified | unqualified)", val, NULL, NULL, NULL);
6282 }
6283 }
6284
6285 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6286 if (attr != NULL) {
6287 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6288 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6289 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6290 xmlSchemaPSimpleTypeErr(ctxt,
6291 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6292 NULL, NULL, (xmlNodePtr) attr, NULL,
6293 "(qualified | unqualified)", val, NULL, NULL, NULL);
6294 }
6295 }
6296
6297 attr = xmlSchemaGetPropNode(node, "finalDefault");
6298 if (attr != NULL) {
6299 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6300 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6301 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6302 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6303 -1,
6304 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6305 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6306 xmlSchemaPSimpleTypeErr(ctxt,
6307 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6308 NULL, NULL, (xmlNodePtr) attr, NULL,
6309 "(#all | List of (extension | restriction | list | union))",
6310 val, NULL, NULL, NULL);
6311 }
6312 }
6313
6314 attr = xmlSchemaGetPropNode(node, "blockDefault");
6315 if (attr != NULL) {
6316 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6317 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6318 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6319 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6320 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6321 xmlSchemaPSimpleTypeErr(ctxt,
6322 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6323 NULL, NULL, (xmlNodePtr) attr, NULL,
6324 "(#all | List of (extension | restriction | substitution))",
6325 val, NULL, NULL, NULL);
6326 }
6327 }
6328}
6329
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006330/**
6331 * xmlSchemaParseSchemaTopLevel:
6332 * @ctxt: a schema validation context
6333 * @schema: the schemas
6334 * @nodes: the list of top level nodes
6335 *
6336 * Returns the internal XML Schema structure built from the resource or
6337 * NULL in case of error
6338 */
6339static void
6340xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6341 xmlSchemaPtr schema, xmlNodePtr nodes)
6342{
6343 xmlNodePtr child;
6344 xmlSchemaAnnotPtr annot;
6345
6346 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6347 return;
6348
6349 child = nodes;
6350 while ((IS_SCHEMA(child, "include")) ||
6351 (IS_SCHEMA(child, "import")) ||
6352 (IS_SCHEMA(child, "redefine")) ||
6353 (IS_SCHEMA(child, "annotation"))) {
6354 if (IS_SCHEMA(child, "annotation")) {
6355 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6356 if (schema->annot == NULL)
6357 schema->annot = annot;
6358 else
6359 xmlSchemaFreeAnnot(annot);
6360 } else if (IS_SCHEMA(child, "import")) {
6361 xmlSchemaParseImport(ctxt, schema, child);
6362 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006363 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006364 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006365 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006366 } else if (IS_SCHEMA(child, "redefine")) {
6367 TODO
6368 }
6369 child = child->next;
6370 }
6371 while (child != NULL) {
6372 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006373 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006374 child = child->next;
6375 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006376 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006377 child = child->next;
6378 } else if (IS_SCHEMA(child, "element")) {
6379 xmlSchemaParseElement(ctxt, schema, child, 1);
6380 child = child->next;
6381 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006382 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006383 child = child->next;
6384 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006385 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006386 child = child->next;
6387 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006388 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006389 child = child->next;
6390 } else if (IS_SCHEMA(child, "notation")) {
6391 xmlSchemaParseNotation(ctxt, schema, child);
6392 child = child->next;
6393 } else {
6394 xmlSchemaPErr2(ctxt, NULL, child,
6395 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006396 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006397 child->name, NULL);
6398 child = child->next;
6399 }
6400 while (IS_SCHEMA(child, "annotation")) {
6401 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6402 if (schema->annot == NULL)
6403 schema->annot = annot;
6404 else
6405 xmlSchemaFreeAnnot(annot);
6406 child = child->next;
6407 }
6408 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006409 ctxt->parentItem = NULL;
6410 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006411}
6412
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006413static xmlSchemaImportPtr
6414xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6415 xmlHashTablePtr *imports,
6416 const xmlChar *nsName)
6417{
6418 xmlSchemaImportPtr ret;
6419
6420 if (*imports == NULL) {
6421 *imports = xmlHashCreate(10);
6422 if (*imports == NULL) {
6423 xmlSchemaPCustomErr(ctxt,
6424 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6425 NULL, NULL, (xmlNodePtr) ctxt->doc,
6426 "Internal error: failed to build the import table",
6427 NULL);
6428 return (NULL);
6429 }
6430 }
6431 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6432 if (ret == NULL) {
6433 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6434 return (NULL);
6435 }
6436 memset(ret, 0, sizeof(xmlSchemaImport));
6437 if (nsName == NULL)
6438 nsName = XML_SCHEMAS_NO_NAMESPACE;
6439 xmlHashAddEntry(*imports, nsName, ret);
6440
6441 return (ret);
6442}
6443
6444static int
6445xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
6446 xmlSchemaPtr schema,
6447 xmlNodePtr node,
6448 const xmlChar *nsName,
6449 const xmlChar *location,
6450 xmlDocPtr *doc,
6451 const xmlChar **targetNamespace,
6452 int absolute)
6453{
6454 xmlParserCtxtPtr parserCtxt;
6455 xmlSchemaImportPtr import;
6456 const xmlChar *ns;
6457 xmlNodePtr root;
6458
6459 /*
6460 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6461 * <xsi:noNamespaceSchemaLocation>.
6462 */
6463 *doc = NULL;
6464 /*
6465 * Given that the schemaLocation [attribute] is only a hint, it is open
6466 * to applications to ignore all but the first <import> for a given
6467 * namespace, regardless of the ·actual value· of schemaLocation, but
6468 * such a strategy risks missing useful information when new
6469 * schemaLocations are offered.
6470 *
6471 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6472 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6473 * valid or not.
6474 * We will follow XSV here.
6475 */
6476 if (location == NULL) {
6477 /*
6478 * Schema Document Location Strategy:
6479 *
6480 * 3 Based on the namespace name, identify an existing schema document,
6481 * either as a resource which is an XML document or a <schema> element
6482 * information item, in some local schema repository;
6483 *
6484 * 5 Attempt to resolve the namespace name to locate such a resource.
6485 *
6486 * NOTE: Those stategies are not supported, so we will skip.
6487 */
6488 return (0);
6489 }
6490 if (nsName == NULL)
6491 ns = XML_SCHEMAS_NO_NAMESPACE;
6492 else
6493 ns = nsName;
6494
6495 import = xmlHashLookup(schema->schemasImports, ns);
6496 if (import != NULL) {
6497 /*
6498 * There was a valid resource for the specified namespace already
6499 * defined, so skip.
6500 * TODO: This might be changed someday to allow import of
6501 * components from multiple documents for a single target namespace.
6502 */
6503 return (0);
6504 }
6505 /*
6506 * Schema Document Location Strategy:
6507 *
6508 * 2 Based on the location URI, identify an existing schema document,
6509 * either as a resource which is an XML document or a <schema> element
6510 * information item, in some local schema repository;
6511 *
6512 * 4 Attempt to resolve the location URI, to locate a resource on the
6513 * web which is or contains or references a <schema> element;
6514 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6515 *
6516 */
6517 if ((absolute == 0) && (node != NULL)) {
6518 xmlChar *base, *URI;
6519
6520 base = xmlNodeGetBase(node->doc, node);
6521 if (base == NULL) {
6522 URI = xmlBuildURI(location, node->doc->URL);
6523 } else {
6524 URI = xmlBuildURI(location, base);
6525 xmlFree(base);
6526 }
6527 if (URI != NULL) {
6528 location = xmlDictLookup(ctxt->dict, URI, -1);
6529 xmlFree(URI);
6530 }
6531 }
6532 parserCtxt = xmlNewParserCtxt();
6533 if (parserCtxt == NULL) {
6534 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6535 "allocating a parser context", NULL);
6536 return(-1);
6537 }
6538
6539 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6540 NULL, SCHEMAS_PARSE_OPTIONS);
6541
6542 /*
6543 * 2.1 The referent is (a fragment of) a resource which is an
6544 * XML document (see clause 1.1), which in turn corresponds to
6545 * a <schema> element information item in a well-formed information
6546 * set, which in turn corresponds to a valid schema.
6547 * TODO: What to do with the "fragment" stuff?
6548 *
6549 * 2.2 The referent is a <schema> element information item in
6550 * a well-formed information set, which in turn corresponds
6551 * to a valid schema.
6552 * NOTE: 2.2 won't apply, since only XML documents will be processed
6553 * here.
6554 */
6555 if (*doc == NULL) {
6556 xmlErrorPtr lerr;
6557 /*
6558 * It is *not* an error for the application schema reference
6559 * strategy to fail.
6560 *
6561 * If the doc is NULL and the parser error is an IO error we
6562 * will assume that the resource could not be located or accessed.
6563 *
6564 * TODO: Try to find specific error codes to react only on
6565 * localisation failures.
6566 *
6567 * TODO, FIXME: Check the spec: is a namespace added to the imported
6568 * namespaces, even if the schemaLocation did not provide
6569 * a resource? I guess so, since omitting the "schemaLocation"
6570 * attribute, imports a namespace as well.
6571 */
6572 lerr = xmlGetLastError();
6573 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6574 xmlFreeParserCtxt(parserCtxt);
6575 return(0);
6576 }
6577
6578 xmlSchemaPCustomErr(ctxt,
6579 XML_SCHEMAP_SRC_IMPORT_2_1,
6580 NULL, NULL, node,
6581 "Failed to parse the resource '%s' for import",
6582 location);
6583 xmlFreeParserCtxt(parserCtxt);
6584 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6585 }
6586 xmlFreeParserCtxt(parserCtxt);
6587
6588 root = xmlDocGetRootElement(*doc);
6589 if (root == NULL) {
6590 xmlSchemaPCustomErr(ctxt,
6591 XML_SCHEMAP_SRC_IMPORT_2_1,
6592 NULL, NULL, node,
6593 "The XML document '%s' to be imported has no document "
6594 "element", location);
6595 xmlFreeDoc(*doc);
6596 *doc = NULL;
6597 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6598 }
6599
6600 xmlSchemaCleanupDoc(ctxt, root);
6601
6602 if (!IS_SCHEMA(root, "schema")) {
6603 xmlSchemaPCustomErr(ctxt,
6604 XML_SCHEMAP_SRC_IMPORT_2_1,
6605 NULL, NULL, node,
6606 "The XML document '%s' to be imported is not a XML schema document",
6607 location);
6608 xmlFreeDoc(*doc);
6609 *doc = NULL;
6610 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6611 }
6612 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6613 /*
6614 * Schema Representation Constraint: Import Constraints and Semantics
6615 */
6616 if (nsName == NULL) {
6617 if (*targetNamespace != NULL) {
6618 xmlSchemaPCustomErr(ctxt,
6619 XML_SCHEMAP_SRC_IMPORT_3_2,
6620 NULL, NULL, node,
6621 "The XML schema to be imported is not expected "
6622 "to have a target namespace; this differs from "
6623 "its target namespace of '%s'", *targetNamespace);
6624 xmlFreeDoc(*doc);
6625 *doc = NULL;
6626 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6627 }
6628 } else {
6629 if (*targetNamespace == NULL) {
6630 xmlSchemaPCustomErr(ctxt,
6631 XML_SCHEMAP_SRC_IMPORT_3_1,
6632 NULL, NULL, node,
6633 "The XML schema to be imported is expected to have a target "
6634 "namespace of '%s'", nsName);
6635 xmlFreeDoc(*doc);
6636 *doc = NULL;
6637 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6638 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6639 xmlSchemaPCustomErrExt(ctxt,
6640 XML_SCHEMAP_SRC_IMPORT_3_1,
6641 NULL, NULL, node,
6642 "The XML schema to be imported is expected to have a "
6643 "target namespace of '%s'; this differs from "
6644 "its target namespace of '%s'",
6645 nsName, *targetNamespace, NULL);
6646 xmlFreeDoc(*doc);
6647 *doc = NULL;
6648 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6649 }
6650 }
6651
6652 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6653 if (import == NULL) {
6654 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6655 NULL, NULL, NULL,
6656 "Internal error: xmlSchemaAcquireSchemaDoc, "
6657 "failed to build import table", NULL);
6658 xmlFreeDoc(*doc);
6659 *doc = NULL;
6660 return (-1);
6661 }
6662 import->schemaLocation = location;
6663 import->doc = *doc;
6664 return (0);
6665}
William M. Brack2f2a6632004-08-20 23:09:47 +00006666
6667/**
6668 * xmlSchemaParseImport:
6669 * @ctxt: a schema validation context
6670 * @schema: the schema being built
6671 * @node: a subtree containing XML Schema informations
6672 *
6673 * parse a XML schema Import definition
6674 * *WARNING* this interface is highly subject to change
6675 *
6676 * Returns 0 in case of success, a positive error code if
6677 * not valid and -1 in case of an internal error.
6678 */
6679static int
6680xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6681 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006682{
6683 xmlNodePtr child;
6684 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006685 const xmlChar *schemaLocation = NULL;
6686 const xmlChar *targetNamespace, *oldTNS, *url;
6687 xmlAttrPtr attr;
6688 xmlDocPtr doc;
6689 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006690 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006691
6692
6693 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6694 return (-1);
6695
6696 /*
6697 * Check for illegal attributes.
6698 */
6699 attr = node->properties;
6700 while (attr != NULL) {
6701 if (attr->ns == NULL) {
6702 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6703 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6704 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6705 xmlSchemaPIllegalAttrErr(ctxt,
6706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6707 NULL, NULL, attr);
6708 }
6709 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6710 xmlSchemaPIllegalAttrErr(ctxt,
6711 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6712 NULL, NULL, attr);
6713 }
6714 attr = attr->next;
6715 }
6716 /*
6717 * Extract and validate attributes.
6718 */
6719 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6720 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6721 &namespace) != 0) {
6722 xmlSchemaPSimpleTypeErr(ctxt,
6723 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6724 NULL, NULL, node,
6725 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6726 NULL, namespace, NULL, NULL, NULL);
6727 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6728 }
6729
6730 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6731 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6732 &schemaLocation) != 0) {
6733 xmlSchemaPSimpleTypeErr(ctxt,
6734 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6735 NULL, NULL, node,
6736 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6737 NULL, namespace, NULL, NULL, NULL);
6738 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6739 }
6740 /*
6741 * And now for the children...
6742 */
6743 child = node->children;
6744 if (IS_SCHEMA(child, "annotation")) {
6745 /*
6746 * the annotation here is simply discarded ...
6747 */
6748 child = child->next;
6749 }
6750 if (child != NULL) {
6751 xmlSchemaPContentErr(ctxt,
6752 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6753 NULL, NULL, node, child, NULL,
6754 "(annotation?)");
6755 }
6756 /*
6757 * Apply additional constraints.
6758 */
6759 if (namespace != NULL) {
6760 /*
6761 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6762 * must not match the ·actual value· of the enclosing <schema>'s
6763 * targetNamespace [attribute].
6764 */
6765 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6766 xmlSchemaPCustomErr(ctxt,
6767 XML_SCHEMAP_SRC_IMPORT_1_1,
6768 NULL, NULL, node,
6769 "The value of the attribute 'namespace' must not match "
6770 "the target namespace '%s' of the importing schema",
6771 schema->targetNamespace);
6772 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6773 }
6774 } else {
6775 /*
6776 * 1.2 If the namespace [attribute] is not present, then the enclosing
6777 * <schema> must have a targetNamespace [attribute].
6778 */
6779 if (schema->targetNamespace == NULL) {
6780 xmlSchemaPCustomErr(ctxt,
6781 XML_SCHEMAP_SRC_IMPORT_1_2,
6782 NULL, NULL, node,
6783 "The attribute 'namespace' must be existent if "
6784 "the importing schema has no target namespace",
6785 NULL);
6786 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6787 }
6788 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006789 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006790 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006791 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006792 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6793 schemaLocation, &doc, &targetNamespace, 0);
6794 if (ret != 0) {
6795 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006796 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006797 return (ret);
6798 } else if (doc != NULL) {
6799 /*
6800 * Save and reset the context & schema.
6801 */
6802 url = ctxt->URL;
6803 /* TODO: Is using the doc->URL here correct? */
6804 ctxt->URL = doc->URL;
6805 flags = schema->flags;
6806 oldTNS = schema->targetNamespace;
6807 /*
6808 * Parse the schema.
6809 */
6810 root = xmlDocGetRootElement(doc);
6811 xmlSchemaClearSchemaDefaults(schema);
6812 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6813 schema->targetNamespace = targetNamespace;
6814 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6815 /*
6816 * Restore the context & schema.
6817 */
6818 schema->flags = flags;
6819 schema->targetNamespace = oldTNS;
6820 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006821 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006822
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006823 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006824}
6825
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006826/**
6827 * xmlSchemaParseInclude:
6828 * @ctxt: a schema validation context
6829 * @schema: the schema being built
6830 * @node: a subtree containing XML Schema informations
6831 *
6832 * parse a XML schema Include definition
6833 *
William M. Bracke7091952004-05-11 15:09:58 +00006834 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006835 * 1 in case of success.
6836 */
6837static int
6838xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6839 xmlNodePtr node)
6840{
6841 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006842 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006843 xmlDocPtr doc;
6844 xmlNodePtr root;
6845 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006846 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006847 xmlAttrPtr attr;
6848 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006849
6850
6851 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6852 return (-1);
6853
6854 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006855 * Check for illegal attributes.
6856 */
6857 attr = node->properties;
6858 while (attr != NULL) {
6859 if (attr->ns == NULL) {
6860 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6861 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6862 xmlSchemaPIllegalAttrErr(ctxt,
6863 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6864 NULL, NULL, attr);
6865 }
6866 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6867 xmlSchemaPIllegalAttrErr(ctxt,
6868 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6869 NULL, NULL, attr);
6870 }
6871 attr = attr->next;
6872 }
6873 /*
6874 * Extract and validate attributes.
6875 */
6876 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006877 * Preliminary step, extract the URI-Reference for the include and
6878 * make an URI from the base.
6879 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006880 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6881 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006882 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006883 xmlChar *uri = NULL;
6884
6885 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6886 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6887 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006888 base = xmlNodeGetBase(node->doc, node);
6889 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006890 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006891 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006892 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006893 xmlFree(base);
6894 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006895 if (uri != NULL) {
6896 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6897 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006898 }
6899 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006900 xmlSchemaPMissingAttrErr(ctxt,
6901 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6902 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006903 return (-1);
6904 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006905 /*
6906 * And now for the children...
6907 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006908 child = node->children;
6909 while (IS_SCHEMA(child, "annotation")) {
6910 /*
6911 * the annotations here are simply discarded ...
6912 */
6913 child = child->next;
6914 }
6915 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006916 xmlSchemaPContentErr(ctxt,
6917 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6918 NULL, NULL, node, child, NULL,
6919 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006920 }
6921
6922 /*
6923 * First step is to parse the input document into an DOM/Infoset
6924 */
6925 doc = xmlReadFile((const char *) schemaLocation, NULL,
6926 SCHEMAS_PARSE_OPTIONS);
6927 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006928 /*
6929 * TODO: It is not an error for the ·actual value· of the
6930 * schemaLocation [attribute] to fail to resolve it all, in which
6931 * case no corresponding inclusion is performed.
6932 * So do we need a warning report here?
6933 */
6934 xmlSchemaPCustomErr(ctxt,
6935 XML_SCHEMAP_FAILED_LOAD,
6936 NULL, NULL, node,
6937 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006938 return(-1);
6939 }
6940
6941 /*
6942 * Then extract the root of the schema
6943 */
6944 root = xmlDocGetRootElement(doc);
6945 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006946 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006947 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006948 NULL, NULL, node,
6949 "The included document '%s' has no document "
6950 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006951 xmlFreeDoc(doc);
6952 return (-1);
6953 }
6954
6955 /*
6956 * Remove all the blank text nodes
6957 */
6958 xmlSchemaCleanupDoc(ctxt, root);
6959
6960 /*
6961 * Check the schemas top level element
6962 */
6963 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006964 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006965 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00006966 NULL, NULL, node,
6967 "The document '%s' to be included is not a schema document",
6968 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006969 xmlFreeDoc(doc);
6970 return (-1);
6971 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006972
William M. Brack2f2a6632004-08-20 23:09:47 +00006973 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006974 /*
6975 * 2.1 SII has a targetNamespace [attribute], and its ·actual
6976 * value· is identical to the ·actual value· of the targetNamespace
6977 * [attribute] of SIIÂ’ (which must have such an [attribute]).
6978 */
6979 if (targetNamespace != NULL) {
6980 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006981 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006982 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006983 NULL, NULL, node,
6984 "The target namespace of the included schema "
6985 "'%s' has to be absent, since the including schema "
6986 "has no target namespace",
6987 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006988 xmlFreeDoc(doc);
6989 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006990 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
6991 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006992 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00006993 NULL, NULL, node,
6994 "The target namespace '%s' of the included schema '%s' "
6995 "differs from '%s' of the including schema",
6996 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006997 xmlFreeDoc(doc);
6998 return (-1);
6999 }
7000 } else if (schema->targetNamespace != NULL) {
7001 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7002 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7003 } else
7004 wasConvertingNs = 1;
7005 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007006 /*
7007 * register the include
7008 */
7009 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7010 if (include == NULL) {
7011 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7012 xmlFreeDoc(doc);
7013 return (-1);
7014 }
7015
7016 memset(include, 0, sizeof(xmlSchemaInclude));
7017 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7018 include->doc = doc;
7019 include->next = schema->includes;
7020 schema->includes = include;
7021
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007022 /*
7023 * parse the declarations in the included file like if they
7024 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007025 */
7026 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007027 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007028 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007029 /*
7030 * The default values ("blockDefault", "elementFormDefault", etc.)
7031 * are set to the values of the included schema and restored afterwards.
7032 */
7033 saveFlags = schema->flags;
7034 xmlSchemaClearSchemaDefaults(schema);
7035 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007036 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007037 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007038 /*
7039 * Remove the converting flag.
7040 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007041 if ((wasConvertingNs == 0) &&
7042 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007043 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007044 return (1);
7045}
7046
7047/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007048 * xmlSchemaParseChoice:
7049 * @ctxt: a schema validation context
7050 * @schema: the schema being built
7051 * @node: a subtree containing XML Schema informations
7052 *
7053 * parse a XML schema Choice definition
7054 * *WARNING* this interface is highly subject to change
7055 *
William M. Bracke7091952004-05-11 15:09:58 +00007056 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007057 * 1 in case of success.
7058 */
7059static xmlSchemaTypePtr
7060xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007061 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007062{
7063 xmlSchemaTypePtr type, subtype, last = NULL;
7064 xmlNodePtr child = NULL;
7065 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007066 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007067
7068 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7069 return (NULL);
7070
7071
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007072 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007073 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007074 if (type == NULL)
7075 return (NULL);
7076 type->node = node;
7077 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007078 /*
7079 * Check for illegal attributes.
7080 */
7081 attr = node->properties;
7082 while (attr != NULL) {
7083 if (attr->ns == NULL) {
7084 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7085 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, type, attr);
7090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, type, attr);
7095 }
7096 attr = attr->next;
7097 }
7098 /*
7099 * Extract and validate attributes.
7100 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007101 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007102 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7103 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7104 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007105 /*
7106 * And now for the children...
7107 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007108 child = node->children;
7109 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007110 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7111 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007112 }
7113 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007114 (IS_SCHEMA(child, "group")) ||
7115 (IS_SCHEMA(child, "any")) ||
7116 (IS_SCHEMA(child, "choice")) ||
7117 (IS_SCHEMA(child, "sequence"))) {
7118 subtype = NULL;
7119 if (IS_SCHEMA(child, "element")) {
7120 subtype = (xmlSchemaTypePtr)
7121 xmlSchemaParseElement(ctxt, schema, child, 0);
7122 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007123 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007124 } else if (IS_SCHEMA(child, "any")) {
7125 subtype = xmlSchemaParseAny(ctxt, schema, child);
7126 } else if (IS_SCHEMA(child, "sequence")) {
7127 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7128 } else if (IS_SCHEMA(child, "choice")) {
7129 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7130 }
7131 if (subtype != NULL) {
7132 if (last == NULL) {
7133 type->subtypes = subtype;
7134 last = subtype;
7135 } else {
7136 last->next = subtype;
7137 last = subtype;
7138 }
7139 last->next = NULL;
7140 }
7141 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007142 }
7143 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007144 /* TODO: error code. */
7145 xmlSchemaPContentErr(ctxt,
7146 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7147 NULL, type, node, child, NULL,
7148 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007149 }
7150
7151 return (type);
7152}
7153
7154/**
7155 * xmlSchemaParseSequence:
7156 * @ctxt: a schema validation context
7157 * @schema: the schema being built
7158 * @node: a subtree containing XML Schema informations
7159 *
7160 * parse a XML schema Sequence definition
7161 * *WARNING* this interface is highly subject to change
7162 *
William M. Bracke7091952004-05-11 15:09:58 +00007163 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007164 * 1 in case of success.
7165 */
7166static xmlSchemaTypePtr
7167xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007168 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007169{
7170 xmlSchemaTypePtr type, subtype, last = NULL;
7171 xmlNodePtr child = NULL;
7172 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007173 xmlAttrPtr attr;
7174 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007175
7176 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7177 return (NULL);
7178
William M. Brack2f2a6632004-08-20 23:09:47 +00007179 oldcontainer = ctxt->container;
7180 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7181 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007182 if (type == NULL)
7183 return (NULL);
7184 type->node = node;
7185 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007186 /*
7187 * Check for illegal attributes.
7188 */
7189 attr = node->properties;
7190 while (attr != NULL) {
7191 if (attr->ns == NULL) {
7192 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7193 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7194 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7195 xmlSchemaPIllegalAttrErr(ctxt,
7196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7197 NULL, type, attr);
7198 }
7199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7200 xmlSchemaPIllegalAttrErr(ctxt,
7201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7202 NULL, type, attr);
7203 }
7204 attr = attr->next;
7205 }
7206 /*
7207 * Extract and validate attributes.
7208 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007209 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007210 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7211 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7212 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007213 /*
7214 * And now for the children...
7215 */
7216 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007217 child = node->children;
7218 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007219 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7220 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221 }
7222 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007223 (IS_SCHEMA(child, "group")) ||
7224 (IS_SCHEMA(child, "any")) ||
7225 (IS_SCHEMA(child, "choice")) ||
7226 (IS_SCHEMA(child, "sequence"))) {
7227 subtype = NULL;
7228 if (IS_SCHEMA(child, "element")) {
7229 subtype = (xmlSchemaTypePtr)
7230 xmlSchemaParseElement(ctxt, schema, child, 0);
7231 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007232 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007233 } else if (IS_SCHEMA(child, "any")) {
7234 subtype = xmlSchemaParseAny(ctxt, schema, child);
7235 } else if (IS_SCHEMA(child, "choice")) {
7236 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7237 } else if (IS_SCHEMA(child, "sequence")) {
7238 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7239 }
7240 if (subtype != NULL) {
7241 if (last == NULL) {
7242 type->subtypes = subtype;
7243 last = subtype;
7244 } else {
7245 last->next = subtype;
7246 last = subtype;
7247 }
7248 last->next = NULL;
7249 }
7250 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007251 }
7252 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007253 xmlSchemaPContentErr(ctxt,
7254 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7255 NULL, type, node, child, NULL,
7256 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007257 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007258 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007259
7260 return (type);
7261}
7262
7263/**
7264 * xmlSchemaParseRestriction:
7265 * @ctxt: a schema validation context
7266 * @schema: the schema being built
7267 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007268 *
7269 * parse a XML schema Restriction definition
7270 * *WARNING* this interface is highly subject to change
7271 *
7272 * Returns the type definition or NULL in case of error
7273 */
7274static xmlSchemaTypePtr
7275xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007276 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007277{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007278 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007279 xmlNodePtr child = NULL;
7280 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007281 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007282 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007283
7284 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7285 return (NULL);
7286
7287 oldcontainer = ctxt->container;
7288
William M. Brack2f2a6632004-08-20 23:09:47 +00007289 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7290 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007291 if (type == NULL)
7292 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007293 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007295 /*
7296 * Check for illegal attributes.
7297 */
7298 attr = node->properties;
7299 while (attr != NULL) {
7300 if (attr->ns == NULL) {
7301 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7302 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7303 xmlSchemaPIllegalAttrErr(ctxt,
7304 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7305 NULL, type, attr);
7306 }
7307 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7308 xmlSchemaPIllegalAttrErr(ctxt,
7309 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7310 NULL, type, attr);
7311 }
7312 attr = attr->next;
7313 }
7314 /*
7315 * Extract and validate attributes.
7316 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007317 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007318 /*
7319 * Attribute "base".
7320 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007321 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007322 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007323 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7324 /* TODO: Think about the error code. */
7325 xmlSchemaPMissingAttrErr(ctxt,
7326 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7327 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007328 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007329 /*
7330 * And now for the children...
7331 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007332 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007333 child = node->children;
7334 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007335 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7336 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 }
7338 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007339 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7340 if (IS_SCHEMA(child, "all")) {
7341 subtype = (xmlSchemaTypePtr)
7342 xmlSchemaParseAll(ctxt, schema, child);
7343 child = child->next;
7344 type->subtypes = subtype;
7345 } else if (IS_SCHEMA(child, "choice")) {
7346 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7347 child = child->next;
7348 type->subtypes = subtype;
7349 } else if (IS_SCHEMA(child, "sequence")) {
7350 subtype = (xmlSchemaTypePtr)
7351 xmlSchemaParseSequence(ctxt, schema, child);
7352 child = child->next;
7353 type->subtypes = subtype;
7354 } else if (IS_SCHEMA(child, "group")) {
7355 subtype = (xmlSchemaTypePtr)
7356 xmlSchemaParseGroup(ctxt, schema, child, 0);
7357 child = child->next;
7358 type->subtypes = subtype;
7359 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007360 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7361 if (IS_SCHEMA(child, "simpleType")) {
7362 if (type->base != NULL) {
7363 /*
7364 * src-restriction-base-or-simpleType
7365 * Either the base [attribute] or the simpleType [child] of the
7366 * <restriction> element must be present, but not both.
7367 */
7368 xmlSchemaPContentErr(ctxt,
7369 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7370 NULL, NULL, type->node, child,
7371 "The attribute 'base' and the <simpleType> child are "
7372 "mutually exclusive", NULL);
7373 } else {
7374 subtype = (xmlSchemaTypePtr)
7375 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7376 type->baseType = subtype;
7377 }
7378 child = child->next;
7379 }
7380 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007381 if (IS_SCHEMA(child, "simpleType")) {
7382 subtype = (xmlSchemaTypePtr)
7383 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007384 type->subtypes = subtype;
7385 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007386 }
7387 }
7388 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7389 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7390 xmlSchemaFacetPtr facet, lastfacet = NULL;
7391
Daniel Veillard01fa6152004-06-29 17:04:39 +00007392 /*
7393 * Add the facets to the parent simpleType/complexType.
7394 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007395 /*
7396 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7397 * Simple Type Definition Schema Representation Constraint:
7398 * *Single Facet Value*
7399 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007400 while ((IS_SCHEMA(child, "minInclusive")) ||
7401 (IS_SCHEMA(child, "minExclusive")) ||
7402 (IS_SCHEMA(child, "maxInclusive")) ||
7403 (IS_SCHEMA(child, "maxExclusive")) ||
7404 (IS_SCHEMA(child, "totalDigits")) ||
7405 (IS_SCHEMA(child, "fractionDigits")) ||
7406 (IS_SCHEMA(child, "pattern")) ||
7407 (IS_SCHEMA(child, "enumeration")) ||
7408 (IS_SCHEMA(child, "whiteSpace")) ||
7409 (IS_SCHEMA(child, "length")) ||
7410 (IS_SCHEMA(child, "maxLength")) ||
7411 (IS_SCHEMA(child, "minLength"))) {
7412 facet = xmlSchemaParseFacet(ctxt, schema, child);
7413 if (facet != NULL) {
7414 if (lastfacet == NULL)
7415 ctxt->ctxtType->facets = facet;
7416 else
7417 lastfacet->next = facet;
7418 lastfacet = facet;
7419 lastfacet->next = NULL;
7420 }
7421 child = child->next;
7422 }
7423 /*
7424 * Create links for derivation and validation.
7425 */
7426 if (lastfacet != NULL) {
7427 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7428
7429 facet = ctxt->ctxtType->facets;
7430 do {
7431 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7432 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007433 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007434 xmlFree(facetLink);
7435 return (NULL);
7436 }
7437 facetLink->facet = facet;
7438 facetLink->next = NULL;
7439 if (lastFacetLink == NULL)
7440 ctxt->ctxtType->facetSet = facetLink;
7441 else
7442 lastFacetLink->next = facetLink;
7443 lastFacetLink = facetLink;
7444 facet = facet->next;
7445 } while (facet != NULL);
7446 }
7447 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007448 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7449 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7450 if (IS_SCHEMA(child, "anyAttribute")) {
7451 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7452 child = child->next;
7453 }
7454 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007455 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007456 /* TODO: Think about the error code. */
7457 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7458 xmlSchemaPContentErr(ctxt,
7459 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7460 NULL, type, node, child, NULL,
7461 "annotation?, (group | all | choice | sequence)?, "
7462 "((attribute | attributeGroup)*, anyAttribute?))");
7463 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7464 xmlSchemaPContentErr(ctxt,
7465 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7466 NULL, type, node, child, NULL,
7467 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7468 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7469 "length | minLength | maxLength | enumeration | whiteSpace | "
7470 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7471 } else {
7472 /* Simple type */
7473 xmlSchemaPContentErr(ctxt,
7474 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7475 NULL, type, node, child, NULL,
7476 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7477 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7478 "length | minLength | maxLength | enumeration | whiteSpace | "
7479 "pattern)*))");
7480 }
7481 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007482 ctxt->container = oldcontainer;
7483 return (type);
7484}
7485
7486/**
7487 * xmlSchemaParseExtension:
7488 * @ctxt: a schema validation context
7489 * @schema: the schema being built
7490 * @node: a subtree containing XML Schema informations
7491 *
7492 * parse a XML schema Extension definition
7493 * *WARNING* this interface is highly subject to change
7494 *
7495 * Returns the type definition or NULL in case of error
7496 */
7497static xmlSchemaTypePtr
7498xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007499 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007500{
7501 xmlSchemaTypePtr type, subtype;
7502 xmlNodePtr child = NULL;
7503 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007504 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007505
7506 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7507 return (NULL);
7508
7509 oldcontainer = ctxt->container;
7510
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007511 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007512 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007513 if (type == NULL)
7514 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007515 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007516 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007517 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007518 ctxt->container = name;
7519
7520 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7521 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007522 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007523 "<extension>: The attribute \"base\" is missing.\n",
7524 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007525 }
7526 child = node->children;
7527 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007528 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7529 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007530 }
7531 subtype = NULL;
7532
7533 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007534 subtype = xmlSchemaParseAll(ctxt, schema, child);
7535 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007536 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007537 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7538 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007539 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007540 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7541 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007542 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007543 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007544 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007545 }
7546 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007547 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007548 if ((ctxt->ctxtType != NULL) &&
7549 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7550 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7551 if (IS_SCHEMA(child, "anyAttribute")) {
7552 ctxt->ctxtType->attributeWildcard =
7553 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7554 child = child->next;
7555 }
7556 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007557 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007558 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7560 "<extension> has unexpected content.\n", type->name,
7561 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007562 }
7563 ctxt->container = oldcontainer;
7564 return (type);
7565}
7566
7567/**
7568 * xmlSchemaParseSimpleContent:
7569 * @ctxt: a schema validation context
7570 * @schema: the schema being built
7571 * @node: a subtree containing XML Schema informations
7572 *
7573 * parse a XML schema SimpleContent definition
7574 * *WARNING* this interface is highly subject to change
7575 *
7576 * Returns the type definition or NULL in case of error
7577 */
7578static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007579xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7580 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007581{
7582 xmlSchemaTypePtr type, subtype;
7583 xmlNodePtr child = NULL;
7584 xmlChar name[30];
7585
7586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7587 return (NULL);
7588
William M. Bracke7091952004-05-11 15:09:58 +00007589 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007590 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007591 if (type == NULL)
7592 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007593 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007594 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007595 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007596
7597 child = node->children;
7598 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007599 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007601 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007602 ctxt->parentItem = type;
7603 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007604 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007605 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007606 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007607 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007608 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007609 subtype = (xmlSchemaTypePtr)
7610 xmlSchemaParseExtension(ctxt, schema, child);
7611 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007612 }
7613 type->subtypes = subtype;
7614 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007615 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7617 "<simpleContent> has unexpected content.\n",
7618 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007619 }
7620 return (type);
7621}
7622
7623/**
7624 * xmlSchemaParseComplexContent:
7625 * @ctxt: a schema validation context
7626 * @schema: the schema being built
7627 * @node: a subtree containing XML Schema informations
7628 *
7629 * parse a XML schema ComplexContent definition
7630 * *WARNING* this interface is highly subject to change
7631 *
7632 * Returns the type definition or NULL in case of error
7633 */
7634static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007635xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7636 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007637{
7638 xmlSchemaTypePtr type, subtype;
7639 xmlNodePtr child = NULL;
7640 xmlChar name[30];
7641
7642 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7643 return (NULL);
7644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007645 snprintf((char *) name, 30, "complexContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007646 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007647 if (type == NULL)
7648 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007649 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007650 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007651 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007652
7653 child = node->children;
7654 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007655 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7656 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007657 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007658 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007659 subtype = NULL;
7660 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007661 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007662 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007663 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007664 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007665 subtype = (xmlSchemaTypePtr)
7666 xmlSchemaParseExtension(ctxt, schema, child);
7667 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007668 }
7669 type->subtypes = subtype;
7670 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007671 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007672 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,
7673 "<complexContent> has unexpected content.\n",
7674 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007675 }
7676 return (type);
7677}
7678
7679/**
7680 * xmlSchemaParseComplexType:
7681 * @ctxt: a schema validation context
7682 * @schema: the schema being built
7683 * @node: a subtree containing XML Schema informations
7684 *
7685 * parse a XML schema Complex Type definition
7686 * *WARNING* this interface is highly subject to change
7687 *
7688 * Returns the type definition or NULL in case of error
7689 */
7690static xmlSchemaTypePtr
7691xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007692 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007693{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007694 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007695 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007696 const xmlChar *name;
William M. Bracke7091952004-05-11 15:09:58 +00007697 const xmlChar *oldcontainer;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007698 char buf[100];
Daniel Veillard4255d502002-04-16 15:50:10 +00007699
7700 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7701 return (NULL);
7702
Daniel Veillard01fa6152004-06-29 17:04:39 +00007703 ctxtType = ctxt->ctxtType;
7704
Daniel Veillard4255d502002-04-16 15:50:10 +00007705 oldcontainer = ctxt->container;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007706 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007707 if (name == NULL) {
William M. Bracke7091952004-05-11 15:09:58 +00007708 snprintf(buf, 99, "complexType %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007709 name = (const xmlChar *)buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00007710 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007711 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007712
William M. Bracke7091952004-05-11 15:09:58 +00007713 /* local = xmlSchemaGetNamespace(ctxt, schema, node, name, &ns); */
William M. Brack2f2a6632004-08-20 23:09:47 +00007714 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007715 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007716 if (type == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00007717 return (NULL);
7718 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007719 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0))
William M. Bracke7091952004-05-11 15:09:58 +00007720 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillard1aefc862004-03-04 11:40:48 +00007721
Daniel Veillard4255d502002-04-16 15:50:10 +00007722 type->node = node;
7723 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007724 /* Set as default for attribute wildcards.
7725 * This will be only changed if a complex type
7726 * inherits an attribute wildcard from a base type.
7727 */
7728 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard3646d642004-06-02 19:19:14 +00007729 if (topLevel)
7730 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007731 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007732 ctxt->container = name;
7733
7734 child = node->children;
7735 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007736 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7737 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007738 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007739 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007740 if (IS_SCHEMA(child, "simpleContent")) {
William M. Bracke7091952004-05-11 15:09:58 +00007741 /* 3.4.3 : 2.2
7742 * Specifying mixed='true' when the <simpleContent>
7743 * alternative is chosen has no effect
7744 */
7745 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7746 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007747 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7748 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007749 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007750 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7751 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007752 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007753 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007754
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007755 if (IS_SCHEMA(child, "all")) {
7756 subtype = xmlSchemaParseAll(ctxt, schema, child);
7757 child = child->next;
7758 } else if (IS_SCHEMA(child, "choice")) {
7759 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7760 child = child->next;
7761 } else if (IS_SCHEMA(child, "sequence")) {
7762 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7763 child = child->next;
7764 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007765 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007766 child = child->next;
7767 }
7768 if (subtype != NULL)
7769 type->subtypes = subtype;
7770 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007771 if (IS_SCHEMA(child, "anyAttribute")) {
7772 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7773 child = child->next;
7774 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007775 }
7776 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007777 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007778 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,
7779 "Complex type definition \"%s\" has unexpected content.\n",
7780 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007781 }
Daniel Veillard3646d642004-06-02 19:19:14 +00007782 if (type->attributeWildcard != NULL)
7783 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillard4255d502002-04-16 15:50:10 +00007784 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007785 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007786 return (type);
7787}
7788
Daniel Veillard4255d502002-04-16 15:50:10 +00007789/**
7790 * xmlSchemaParseSchema:
7791 * @ctxt: a schema validation context
7792 * @node: a subtree containing XML Schema informations
7793 *
7794 * parse a XML schema definition from a node set
7795 * *WARNING* this interface is highly subject to change
7796 *
7797 * Returns the internal XML Schema structure built from the resource or
7798 * NULL in case of error
7799 */
7800static xmlSchemaPtr
7801xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
7802{
7803 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007804 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007805 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007806 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007807
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007808 /*
7809 * This one is called by xmlSchemaParse only and is used if
7810 * the schema to be parsed was specified via the API; i.e. not
7811 * automatically by the validated instance document.
7812 */
7813
Daniel Veillard4255d502002-04-16 15:50:10 +00007814 if ((ctxt == NULL) || (node == NULL))
7815 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007816
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007817 nberrors = ctxt->nberrors;
7818 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007819 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007820 xmlSchemaImportPtr import;
7821
Daniel Veillard4255d502002-04-16 15:50:10 +00007822 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007823 if (schema == NULL)
7824 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007825 /*
7826 * Disable build of list of items.
7827 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007828 attr = xmlSchemaGetPropNode(node, "targetNamespace");
7829 if (attr != NULL) {
7830 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7831 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
7832 /*
7833 * TODO: Should we proceed with an invalid target namespace?
7834 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007835 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
7836 } else {
7837 schema->targetNamespace = NULL;
7838 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007839 /*
7840 * Add the current ns name and location to the import table;
7841 * this is needed to have a consistent mechanism, regardless
7842 * if all schemata are constructed dynamically fired by the
7843 * instance or if the schema to be used was specified via
7844 * the API.
7845 */
7846 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
7847 schema->targetNamespace);
7848 if (import == NULL) {
7849 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7850 NULL, NULL, (xmlNodePtr) ctxt->doc,
7851 "Internal error: xmlSchemaParseSchema, "
7852 "failed to add an import entry", NULL);
7853 xmlSchemaFree(schema);
7854 schema = NULL;
7855 return (NULL);
7856 }
7857 import->schemaLocation = ctxt->URL;
7858 /*
7859 * NOTE: We won't set the doc here, otherwise it will be freed
7860 * if the import struct is freed.
7861 * import->doc = ctxt->doc;
7862 */
7863
Daniel Veillardc0826a72004-08-10 14:17:33 +00007864 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007865 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007866 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7867 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7868
William M. Brack2f2a6632004-08-20 23:09:47 +00007869 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007870 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
7871 } else {
7872 xmlDocPtr doc;
7873
7874 doc = node->doc;
7875
7876 if ((doc != NULL) && (doc->URL != NULL)) {
7877 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7878 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007879 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007880 } else {
7881 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
7882 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007883 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007884 }
7885 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007886 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007887 if (ctxt->nberrors != 0) {
7888 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007889 xmlSchemaFree(schema);
7890 schema = NULL;
7891 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00007892 }
7893 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00007894#ifdef DEBUG
7895 if (schema == NULL)
7896 xmlGenericError(xmlGenericErrorContext,
7897 "xmlSchemaParse() failed\n");
7898#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00007899 return (schema);
7900}
7901
7902/************************************************************************
7903 * *
7904 * Validating using Schemas *
7905 * *
7906 ************************************************************************/
7907
7908/************************************************************************
7909 * *
7910 * Reading/Writing Schemas *
7911 * *
7912 ************************************************************************/
7913
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007914#if 0 /* Will be enabled if it is clear what options are needed. */
7915/**
7916 * xmlSchemaParserCtxtSetOptions:
7917 * @ctxt: a schema parser context
7918 * @options: a combination of xmlSchemaParserOption
7919 *
7920 * Sets the options to be used during the parse.
7921 *
7922 * Returns 0 in case of success, -1 in case of an
7923 * API error.
7924 */
7925static int
7926xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
7927 int options)
7928
7929{
7930 int i;
7931
7932 if (ctxt == NULL)
7933 return (-1);
7934 /*
7935 * WARNING: Change the start value if adding to the
7936 * xmlSchemaParseOption.
7937 */
7938 for (i = 1; i < (int) sizeof(int) * 8; i++) {
7939 if (options & 1<<i) {
7940 return (-1);
7941 }
7942 }
7943 ctxt->options = options;
7944 return (0);
7945}
7946
7947/**
7948 * xmlSchemaValidCtxtGetOptions:
7949 * @ctxt: a schema parser context
7950 *
7951 * Returns the option combination of the parser context.
7952 */
7953static int
7954xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
7955
7956{
7957 if (ctxt == NULL)
7958 return (-1);
7959 else
7960 return (ctxt->options);
7961}
7962
7963 void *curItems; /* used for dynamic addition of schemata */
7964 int nbCurItems; /* used for dynamic addition of schemata */
7965 int sizeCurItems; /* used for dynamic addition of schemata */
7966
7967#endif
7968
Daniel Veillard4255d502002-04-16 15:50:10 +00007969/**
7970 * xmlSchemaNewParserCtxt:
7971 * @URL: the location of the schema
7972 *
7973 * Create an XML Schemas parse context for that file/resource expected
7974 * to contain an XML Schemas file.
7975 *
7976 * Returns the parser context or NULL in case of error
7977 */
7978xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007979xmlSchemaNewParserCtxt(const char *URL)
7980{
Daniel Veillard4255d502002-04-16 15:50:10 +00007981 xmlSchemaParserCtxtPtr ret;
7982
7983 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007984 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007985
7986 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7987 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007988 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007990 return (NULL);
7991 }
7992 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007993 ret->dict = xmlDictCreate();
7994 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007995 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00007996 return (ret);
7997}
7998
7999/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008000 * xmlSchemaNewParserCtxtUseDict:
8001 * @URL: the location of the schema
8002 * @dict: the dictionary to be used
8003 *
8004 * Create an XML Schemas parse context for that file/resource expected
8005 * to contain an XML Schemas file.
8006 *
8007 * Returns the parser context or NULL in case of error
8008 */
8009static xmlSchemaParserCtxtPtr
8010xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8011{
8012 xmlSchemaParserCtxtPtr ret;
8013
8014 if (URL == NULL)
8015 return (NULL);
8016
8017 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8018 if (ret == NULL) {
8019 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8020 NULL);
8021 return (NULL);
8022 }
8023 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8024 ret->dict = dict;
8025 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8026 ret->includes = 0;
8027 return (ret);
8028}
8029
8030
8031/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008032 * xmlSchemaNewMemParserCtxt:
8033 * @buffer: a pointer to a char array containing the schemas
8034 * @size: the size of the array
8035 *
8036 * Create an XML Schemas parse context for that memory buffer expected
8037 * to contain an XML Schemas file.
8038 *
8039 * Returns the parser context or NULL in case of error
8040 */
8041xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008042xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8043{
Daniel Veillard6045c902002-10-09 21:13:59 +00008044 xmlSchemaParserCtxtPtr ret;
8045
8046 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008047 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008048
8049 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8050 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008052 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008053 return (NULL);
8054 }
8055 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8056 ret->buffer = buffer;
8057 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008058 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008059 return (ret);
8060}
8061
8062/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008063 * xmlSchemaNewDocParserCtxt:
8064 * @doc: a preparsed document tree
8065 *
8066 * Create an XML Schemas parse context for that document.
8067 * NB. The document may be modified during the parsing process.
8068 *
8069 * Returns the parser context or NULL in case of error
8070 */
8071xmlSchemaParserCtxtPtr
8072xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8073{
8074 xmlSchemaParserCtxtPtr ret;
8075
8076 if (doc == NULL)
8077 return (NULL);
8078
8079 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8080 if (ret == NULL) {
8081 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8082 NULL);
8083 return (NULL);
8084 }
8085 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8086 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008087 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008088 /* The application has responsibility for the document */
8089 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008090
8091 return (ret);
8092}
8093
8094/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008095 * xmlSchemaFreeParserCtxt:
8096 * @ctxt: the schema parser context
8097 *
8098 * Free the resources associated to the schema parser context
8099 */
8100void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008101xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8102{
Daniel Veillard4255d502002-04-16 15:50:10 +00008103 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008104 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008105 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008106 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008107 if (ctxt->assemble != NULL) {
8108 xmlFree(ctxt->assemble->items);
8109 xmlFree(ctxt->assemble);
8110 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008111 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008112 xmlFree(ctxt);
8113}
8114
8115/************************************************************************
8116 * *
8117 * Building the content models *
8118 * *
8119 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008120
Daniel Veillard4255d502002-04-16 15:50:10 +00008121/**
8122 * xmlSchemaBuildAContentModel:
8123 * @type: the schema type definition
8124 * @ctxt: the schema parser context
8125 * @name: the element name whose content is being built
8126 *
8127 * Generate the automata sequence needed for that type
8128 */
8129static void
8130xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008131 xmlSchemaParserCtxtPtr ctxt,
8132 const xmlChar * name)
8133{
Daniel Veillard4255d502002-04-16 15:50:10 +00008134 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008135 xmlGenericError(xmlGenericErrorContext,
8136 "Found unexpected type = NULL in %s content model\n",
8137 name);
8138 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008139 }
8140 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008141 case XML_SCHEMA_TYPE_ANY: {
8142 xmlAutomataStatePtr start, end;
8143 xmlSchemaWildcardPtr wild;
8144 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008145
Daniel Veillardc0826a72004-08-10 14:17:33 +00008146 wild = type->attributeWildcard;
8147
8148 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008149 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 "Internal error: xmlSchemaBuildAContentModel, "
8151 "no wildcard on xsd:any.\n", NULL, NULL);
8152 return;
8153 }
8154
8155 start = ctxt->state;
8156 end = xmlAutomataNewState(ctxt->am);
8157
8158 if (type->maxOccurs == 1) {
8159 if (wild->any == 1) {
8160 /*
8161 * We need to add both transitions:
8162 *
8163 * 1. the {"*", "*"} for elements in a namespace.
8164 */
8165 ctxt->state =
8166 xmlAutomataNewTransition2(ctxt->am,
8167 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8168 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8169 /*
8170 * 2. the {"*"} for elements in no namespace.
8171 */
8172 ctxt->state =
8173 xmlAutomataNewTransition2(ctxt->am,
8174 start, NULL, BAD_CAST "*", NULL, type);
8175 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8176
8177 } else if (wild->nsSet != NULL) {
8178 ns = wild->nsSet;
8179 do {
8180 ctxt->state = start;
8181 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8182 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8183 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8184 ns = ns->next;
8185 } while (ns != NULL);
8186
8187 } else if (wild->negNsSet != NULL) {
8188 xmlAutomataStatePtr deadEnd;
8189
8190 deadEnd = xmlAutomataNewState(ctxt->am);
8191 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8192 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8193 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8194 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8195 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8196 }
8197 } else {
8198 int counter;
8199 xmlAutomataStatePtr hop;
8200 int maxOccurs =
8201 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8202 int minOccurs =
8203 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8204
8205 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8206 hop = xmlAutomataNewState(ctxt->am);
8207 if (wild->any == 1) {
8208 ctxt->state =
8209 xmlAutomataNewTransition2(ctxt->am,
8210 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8211 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8212 ctxt->state =
8213 xmlAutomataNewTransition2(ctxt->am,
8214 start, NULL, BAD_CAST "*", NULL, type);
8215 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8216 } else if (wild->nsSet != NULL) {
8217 ns = wild->nsSet;
8218 do {
8219 ctxt->state =
8220 xmlAutomataNewTransition2(ctxt->am,
8221 start, NULL, BAD_CAST "*", ns->value, type);
8222 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8223 ns = ns->next;
8224 } while (ns != NULL);
8225
8226 } else if (wild->negNsSet != NULL) {
8227 xmlAutomataStatePtr deadEnd;
8228
8229 deadEnd = xmlAutomataNewState(ctxt->am);
8230 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8231 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8232 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8233 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8234 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8235 }
8236 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8237 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8238 }
8239 if (type->minOccurs == 0) {
8240 xmlAutomataNewEpsilon(ctxt->am, start, end);
8241 }
8242 ctxt->state = end;
8243 break;
8244 }
8245 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008246 xmlAutomataStatePtr oldstate;
8247 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008248
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008249 /*
8250 * IMPORTANT: This puts element declarations
8251 * (and never element decl. references) into the
8252 * automaton. This is crucial and should not be changed,
8253 * since validating functions rely now on it.
8254 */
8255 particle = (xmlSchemaElementPtr) type;
8256 if (particle->ref != NULL) {
8257 if (particle->refDecl == NULL) {
8258 /*
8259 * Skip content model creation if the reference
8260 * did not resolve to a declaration.
8261 */
8262 break;
8263 } else {
8264 /*
8265 * Referenced global element declaration.
8266 */
8267 elemDecl = particle->refDecl;
8268 }
8269 } else {
8270 /*
8271 * Anonymous element declaration.
8272 */
8273 elemDecl = particle;
8274 }
8275
8276 oldstate = ctxt->state;
8277
8278 if (particle->maxOccurs >= UNBOUNDED) {
8279 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008280 xmlAutomataStatePtr tmp;
8281 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008282
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008283 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008284 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008285 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008286 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008287 particle->minOccurs - 1, UNBOUNDED);
8288 ctxt->state =
8289 xmlAutomataNewTransition2(ctxt->am,
8290 ctxt->state, NULL,
8291 elemDecl->name,
8292 elemDecl->targetNamespace,
8293 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008294 tmp = ctxt->state;
8295 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008296 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008297 ctxt->state =
8298 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008299 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008300
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008301 } else {
8302 ctxt->state =
8303 xmlAutomataNewTransition2(ctxt->am,
8304 ctxt->state, NULL,
8305 elemDecl->name,
8306 elemDecl->targetNamespace,
8307 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008308 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8309 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008310 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008311 /* basically an elem* */
8312 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8313 ctxt->state);
8314 }
8315 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008316 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008317 xmlAutomataStatePtr tmp;
8318 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008319
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008320 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8321 oldstate, NULL);
8322 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008323 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008324 particle->minOccurs - 1,
8325 particle->maxOccurs - 1);
8326 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8327 ctxt->state,
8328 NULL,
8329 elemDecl->name,
8330 elemDecl->targetNamespace,
8331 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008332 tmp = ctxt->state;
8333 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008334 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008335 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008336 NULL, counter);
8337 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008338 /* basically an elem? */
8339 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008340 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008341 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008342
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008343 } else {
8344 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8345 ctxt->state,
8346 NULL,
8347 elemDecl->name,
8348 elemDecl->targetNamespace,
8349 (xmlSchemaTypePtr) elemDecl);
8350 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008351 /* basically an elem? */
8352 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008353 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008354 }
8355 }
8356 break;
8357 }
8358 case XML_SCHEMA_TYPE_SEQUENCE:{
8359 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008360
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008361 /*
8362 * If max and min occurances are default (1) then
8363 * simply iterate over the subtypes
8364 */
8365 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8366 subtypes = type->subtypes;
8367 while (subtypes != NULL) {
8368 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8369 subtypes = subtypes->next;
8370 }
8371 } else {
8372 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008373
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008374 if (type->maxOccurs >= UNBOUNDED) {
8375 if (type->minOccurs > 1) {
8376 xmlAutomataStatePtr tmp;
8377 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008378
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008379 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8380 oldstate,
8381 NULL);
8382 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008383
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008384 counter = xmlAutomataNewCounter(ctxt->am,
8385 type->
8386 minOccurs - 1,
8387 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008388
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008389 subtypes = type->subtypes;
8390 while (subtypes != NULL) {
8391 xmlSchemaBuildAContentModel(subtypes, ctxt,
8392 name);
8393 subtypes = subtypes->next;
8394 }
8395 tmp = ctxt->state;
8396 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8397 oldstate, counter);
8398 ctxt->state =
8399 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8400 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008401
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008402 } else {
8403 subtypes = type->subtypes;
8404 while (subtypes != NULL) {
8405 xmlSchemaBuildAContentModel(subtypes, ctxt,
8406 name);
8407 subtypes = subtypes->next;
8408 }
8409 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8410 oldstate);
8411 if (type->minOccurs == 0) {
8412 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8413 ctxt->state);
8414 }
8415 }
8416 } else if ((type->maxOccurs > 1)
8417 || (type->minOccurs > 1)) {
8418 xmlAutomataStatePtr tmp;
8419 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008420
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008421 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8422 oldstate,
8423 NULL);
8424 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008425
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008426 counter = xmlAutomataNewCounter(ctxt->am,
8427 type->minOccurs -
8428 1,
8429 type->maxOccurs -
8430 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008431
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008432 subtypes = type->subtypes;
8433 while (subtypes != NULL) {
8434 xmlSchemaBuildAContentModel(subtypes, ctxt,
8435 name);
8436 subtypes = subtypes->next;
8437 }
8438 tmp = ctxt->state;
8439 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8440 counter);
8441 ctxt->state =
8442 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8443 counter);
8444 if (type->minOccurs == 0) {
8445 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8446 ctxt->state);
8447 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008448
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008449 } else {
8450 subtypes = type->subtypes;
8451 while (subtypes != NULL) {
8452 xmlSchemaBuildAContentModel(subtypes, ctxt,
8453 name);
8454 subtypes = subtypes->next;
8455 }
8456 if (type->minOccurs == 0) {
8457 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8458 ctxt->state);
8459 }
8460 }
8461 }
8462 break;
8463 }
8464 case XML_SCHEMA_TYPE_CHOICE:{
8465 xmlSchemaTypePtr subtypes;
8466 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008467
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008468 start = ctxt->state;
8469 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008470
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008471 /*
8472 * iterate over the subtypes and remerge the end with an
8473 * epsilon transition
8474 */
8475 if (type->maxOccurs == 1) {
8476 subtypes = type->subtypes;
8477 while (subtypes != NULL) {
8478 ctxt->state = start;
8479 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8480 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8481 subtypes = subtypes->next;
8482 }
8483 } else {
8484 int counter;
8485 xmlAutomataStatePtr hop;
8486 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8487 UNBOUNDED : type->maxOccurs - 1;
8488 int minOccurs =
8489 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008491 /*
8492 * use a counter to keep track of the number of transtions
8493 * which went through the choice.
8494 */
8495 counter =
8496 xmlAutomataNewCounter(ctxt->am, minOccurs,
8497 maxOccurs);
8498 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008499
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008500 subtypes = type->subtypes;
8501 while (subtypes != NULL) {
8502 ctxt->state = start;
8503 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8504 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8505 subtypes = subtypes->next;
8506 }
8507 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8508 counter);
8509 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8510 counter);
8511 }
8512 if (type->minOccurs == 0) {
8513 xmlAutomataNewEpsilon(ctxt->am, start, end);
8514 }
8515 ctxt->state = end;
8516 break;
8517 }
8518 case XML_SCHEMA_TYPE_ALL:{
8519 xmlAutomataStatePtr start;
8520 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008521
Daniel Veillard3646d642004-06-02 19:19:14 +00008522 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008523 int lax;
8524
8525 subtypes = type->subtypes;
8526 if (subtypes == NULL)
8527 break;
8528 start = ctxt->state;
8529 while (subtypes != NULL) {
8530 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008531 /*
8532 * the following 'if' was needed to fix bug 139897
8533 * not quite sure why it only needs to be done for
8534 * elements with a 'ref', but it seems to work ok.
8535 */
8536 if (subtypes->ref != NULL)
8537 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
William M. Bracke7091952004-05-11 15:09:58 +00008538 elem = (xmlSchemaElementPtr) subtypes;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008539 /* TODO : handle the namespace too */
8540 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
8541 xmlAutomataNewOnceTrans(ctxt->am, ctxt->state,
8542 ctxt->state, elem->name, 1,
8543 1, subtypes);
8544 } else {
8545 xmlAutomataNewCountTrans(ctxt->am, ctxt->state,
8546 ctxt->state, elem->name,
8547 elem->minOccurs,
8548 elem->maxOccurs,
8549 subtypes);
8550 }
8551 subtypes = subtypes->next;
8552 }
8553 lax = type->minOccurs == 0;
8554 ctxt->state =
8555 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8556 lax);
8557 break;
8558 }
8559 case XML_SCHEMA_TYPE_RESTRICTION:
8560 if (type->subtypes != NULL)
8561 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8562 break;
8563 case XML_SCHEMA_TYPE_EXTENSION:
8564 if (type->baseType != NULL) {
8565 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008566
8567 /*
8568 * TODO: Circular definitions will be checked at the
8569 * constraint level. So remove this when the complex type
8570 * constraints are implemented.
8571 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008572 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008573 /* TODO: Change the error code. */
8574 xmlSchemaPCustomErr(ctxt,
8575 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8576 NULL, type, type->node,
8577 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008578 return;
8579 }
8580 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008581 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008582 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008583 subtypes = type->subtypes;
8584 while (subtypes != NULL) {
8585 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8586 subtypes = subtypes->next;
8587 }
8588 } else if (type->subtypes != NULL)
8589 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8590 break;
8591 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008592 /*
8593 * Handle model group definition references.
8594 * NOTE: type->subtypes is the referenced model grop definition;
8595 * and type->subtypes->subtypes is the model group (i.e. <all> or
8596 * <choice> or <sequence>).
8597 */
8598 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8599 (type->subtypes->subtypes != NULL)) {
8600 xmlSchemaTypePtr modelGr;
8601 xmlAutomataStatePtr start, end;
8602
8603 modelGr = type->subtypes->subtypes;
8604 start = ctxt->state;
8605 end = xmlAutomataNewState(ctxt->am);
8606 if (type->maxOccurs == 1) {
8607 ctxt->state = start;
8608 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8609 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8610 } else {
8611 int counter;
8612 xmlAutomataStatePtr hop;
8613 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8614 UNBOUNDED : type->maxOccurs - 1;
8615 int minOccurs =
8616 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8617
8618 counter =
8619 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8620 hop = xmlAutomataNewState(ctxt->am);
8621 ctxt->state = start;
8622 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8623 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8624 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8625 counter);
8626 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8627 counter);
8628 }
8629 if (type->minOccurs == 0) {
8630 xmlAutomataNewEpsilon(ctxt->am, start, end);
8631 }
8632 ctxt->state = end;
8633 break;
8634 }
8635 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008636 case XML_SCHEMA_TYPE_COMPLEX:
8637 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8638 if (type->subtypes != NULL)
8639 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8640 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008641 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8642 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008643 default:
8644 xmlGenericError(xmlGenericErrorContext,
8645 "Found unexpected type %d in %s content model\n",
8646 type->type, name);
8647 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008648 }
8649}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008650
Daniel Veillard4255d502002-04-16 15:50:10 +00008651/**
8652 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008653 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008654 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008655 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008656 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008657 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008658 */
8659static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008660xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008661 xmlSchemaParserCtxtPtr ctxt,
8662 const xmlChar * name)
8663{
Daniel Veillard4255d502002-04-16 15:50:10 +00008664 xmlAutomataStatePtr start;
8665
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008666 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8667 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8668 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8669 (type->contModel != NULL))
8670 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008671
8672#ifdef DEBUG_CONTENT
8673 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008675#endif
8676
Daniel Veillard4255d502002-04-16 15:50:10 +00008677 ctxt->am = xmlNewAutomata();
8678 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008679 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008680 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008681 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008682 }
8683 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008684 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008685 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008686 type->contModel = xmlAutomataCompile(ctxt->am);
8687 if (type->contModel == NULL) {
8688 xmlSchemaPCustomErr(ctxt,
8689 XML_SCHEMAP_INTERNAL,
8690 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008691 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008692 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008693 xmlSchemaPCustomErr(ctxt,
8694 XML_SCHEMAP_NOT_DETERMINISTIC,
8695 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008696 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008697 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008698 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008699#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008700 xmlGenericError(xmlGenericErrorContext,
8701 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008702 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008703#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008704 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008705 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008706 xmlFreeAutomata(ctxt->am);
8707 ctxt->am = NULL;
8708}
8709
8710/**
8711 * xmlSchemaRefFixupCallback:
8712 * @elem: the schema element context
8713 * @ctxt: the schema parser context
8714 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008715 * Resolves the references of an element declaration
8716 * or particle, which has an element declaration as it's
8717 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008718 */
8719static void
8720xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008721 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008722 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008723 const xmlChar * context ATTRIBUTE_UNUSED,
8724 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008725{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008726 if ((ctxt == NULL) || (elem == NULL) ||
8727 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008728 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008729 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008730 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008731 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008732
Daniel Veillardc0826a72004-08-10 14:17:33 +00008733 /*
8734 * TODO: Evaluate, what errors could occur if the declaration is not
8735 * found. It might be possible that the "typefixup" might crash if
8736 * no ref declaration was found.
8737 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008738 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008739 if (elemDecl == NULL) {
8740 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008741 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008742 NULL, (xmlSchemaTypePtr) elem, elem->node,
8743 "ref", elem->ref, elem->refNs,
8744 XML_SCHEMA_TYPE_ELEMENT, NULL);
8745 } else
8746 elem->refDecl = elemDecl;
8747 } else {
8748 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8749 xmlSchemaTypePtr type;
8750
8751 /* (type definition) ... otherwise the type definition ·resolved·
8752 * to by the ·actual value· of the type [attribute] ...
8753 */
8754 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8755 elem->namedTypeNs);
8756 if (type == NULL) {
8757 xmlSchemaPResCompAttrErr(ctxt,
8758 XML_SCHEMAP_SRC_RESOLVE,
8759 NULL, (xmlSchemaTypePtr) elem, elem->node,
8760 "type", elem->namedType, elem->namedTypeNs,
8761 XML_SCHEMA_TYPE_BASIC, "type definition");
8762 } else
8763 elem->subtypes = type;
8764 }
8765 if (elem->substGroup != NULL) {
8766 xmlSchemaElementPtr substHead;
8767
8768 /*
8769 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8770 * substitutionGroup?
8771 */
8772 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008773 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008774 if (substHead == NULL) {
8775 xmlSchemaPResCompAttrErr(ctxt,
8776 XML_SCHEMAP_SRC_RESOLVE,
8777 NULL, (xmlSchemaTypePtr) elem, NULL,
8778 "substitutionGroup", elem->substGroup, elem->substGroupNs,
8779 XML_SCHEMA_TYPE_ELEMENT, NULL);
8780 } else {
8781 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
8782 /*
8783 * (type definition)...otherwise the {type definition} of the
8784 * element declaration ·resolved· to by the ·actual value· of
8785 * the substitutionGroup [attribute], if present
8786 */
8787 if (elem->subtypes == NULL)
8788 elem->subtypes = substHead->subtypes;
8789 }
8790 }
8791 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
8792 (elem->substGroup == NULL))
8793 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
8794 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008795}
8796
William M. Bracke7091952004-05-11 15:09:58 +00008797/**
8798 * xmlSchemaParseListRefFixup:
8799 * @type: the schema type definition
8800 * @ctxt: the schema parser context
8801 *
8802 * Fixup of the itemType reference of the list type.
8803 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008804static void
William M. Bracke7091952004-05-11 15:09:58 +00008805xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00008806{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008807
Daniel Veillard01fa6152004-06-29 17:04:39 +00008808 if (((type->base == NULL) &&
8809 (type->subtypes == NULL)) ||
8810 ((type->base != NULL) &&
8811 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008812 /*
8813 * src-list-itemType-or-simpleType
8814 * Either the itemType [attribute] or the <simpleType> [child] of
8815 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008816 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008817 /*
8818 * TODO: Move this to the parse function.
8819 */
8820 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008821 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008822 NULL, type, type->node,
8823 "The attribute 'itemType' and the <simpleType> child "
8824 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008825 } else if (type->base!= NULL) {
8826 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
8827 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008828 xmlSchemaPResCompAttrErr(ctxt,
8829 XML_SCHEMAP_SRC_RESOLVE,
8830 NULL, type, type->node,
8831 "itemType", type->base, type->baseNs,
8832 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008833 }
8834 }
8835 if ((type->subtypes != NULL) &&
8836 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
8837 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00008838}
8839
8840/**
8841 * xmlSchemaParseUnionRefCheck:
8842 * @typeDecl: the schema type definition
8843 * @ctxt: the schema parser context
8844 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00008845 * Checks and builds the memberTypes of the union type.
8846 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00008847 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008848static int
William M. Bracke7091952004-05-11 15:09:58 +00008849xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00008850 xmlSchemaParserCtxtPtr ctxt)
8851{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008852
Daniel Veillard01fa6152004-06-29 17:04:39 +00008853 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
8854 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00008855
Daniel Veillard01fa6152004-06-29 17:04:39 +00008856 /* 1 If the <union> alternative is chosen, then [Definition:]
8857 * define the explicit members as the type definitions ·resolved·
8858 * to by the items in the ·actual value· of the memberTypes [attribute],
8859 * if any, followed by the type definitions corresponding to the
8860 * <simpleType>s among the [children] of <union>, if any.
8861 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00008862
Daniel Veillard01fa6152004-06-29 17:04:39 +00008863 if (type->type != XML_SCHEMA_TYPE_UNION)
8864 return (-1);
8865 if (ctxt->ctxtType == NULL) {
8866 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008867 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008868 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
8869 "available", NULL, NULL);
8870 return (-1);
8871 }
8872 /*
8873 * src-union-memberTypes-or-simpleTypes
8874 * Either the memberTypes [attribute] of the <union> element must
8875 * be non-empty or there must be at least one simpleType [child].
8876 */
8877 if ((type->base == NULL) &&
8878 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008879 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008880 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008881 NULL, NULL, type->node,
8882 "Either the attribute 'memberTypes' must be non-empty "
8883 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008884 }
8885
8886 ctxtType = ctxt->ctxtType;
8887 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008888 xmlAttrPtr attr;
8889 const xmlChar *cur, *end;
8890 xmlChar *tmp;
8891 const xmlChar *localName, *uri;
8892
8893 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00008894 cur = type->base;
8895 do {
8896 while (IS_BLANK_CH(*cur))
8897 cur++;
8898 end = cur;
8899 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8900 end++;
8901 if (end == cur)
8902 break;
8903 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008904 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
8905 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
8906 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008907 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008908 xmlSchemaPResCompAttrErr(ctxt,
8909 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
8910 NULL, NULL, type->node, "memberTypes", localName, uri,
8911 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008912 } else {
8913 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8914 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8915 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8916 if (link == NULL) {
8917 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8918 return (-1);
8919 }
8920 link->type = memberType;
8921 link->next = NULL;
8922 if (lastLink == NULL)
8923 ctxtType->memberTypes = link;
8924 else
8925 lastLink->next = link;
8926 lastLink = link;
8927 }
8928 xmlFree(tmp);
8929 cur = end;
8930 } while (*cur != 0);
8931 }
8932 /*
8933 * Add local simple types,
8934 */
8935 memberType = type->subtypes;
8936 while (memberType != NULL) {
8937 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
8938 xmlSchemaTypeFixup(memberType, ctxt, NULL);
8939 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
8940 if (link == NULL) {
8941 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
8942 return (-1);
8943 }
8944 link->type = memberType;
8945 link->next = NULL;
8946 if (lastLink == NULL)
8947 ctxtType->memberTypes = link;
8948 else
8949 lastLink->next = link;
8950 lastLink = link;
8951 memberType = memberType->next;
8952 }
8953 /*
8954 * The actual value is then formed by replacing any union type
8955 * definition in the ·explicit members· with the members of their
8956 * {member type definitions}, in order.
8957 */
8958 link = ctxtType->memberTypes;
8959 while (link != NULL) {
8960 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
8961 subLink = link->type->memberTypes;
8962 if (subLink != NULL) {
8963 link->type = subLink->type;
8964 if (subLink->next != NULL) {
8965 lastLink = link->next;
8966 subLink = subLink->next;
8967 prevLink = link;
8968 while (subLink != NULL) {
8969 newLink = (xmlSchemaTypeLinkPtr)
8970 xmlMalloc(sizeof(xmlSchemaTypeLink));
8971 if (newLink == NULL) {
8972 xmlSchemaPErrMemory(ctxt, "allocating a type link",
8973 NULL);
8974 return (-1);
8975 }
8976 newLink->type = memberType;
8977 prevLink->next = newLink;
8978 prevLink = newLink;
8979 newLink->next = lastLink;
8980
8981 subLink = subLink->next;
8982 }
8983 }
8984 }
8985 }
8986 link = link->next;
8987 }
8988
8989 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00008990}
8991
Daniel Veillard4255d502002-04-16 15:50:10 +00008992/**
Daniel Veillard3646d642004-06-02 19:19:14 +00008993 * xmlSchemaIsDerivedFromBuiltInType:
8994 * @ctxt: the schema parser context
8995 * @type: the type definition
8996 * @valType: the value type
8997 *
8998 *
8999 * Returns 1 if the type has the given value type, or
9000 * is derived from such a type.
9001 */
William M. Brack803812b2004-06-03 02:11:24 +00009002static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009003xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9004 xmlSchemaTypePtr type, int valType)
9005{
9006 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009007 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009008 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009009 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009010 return(1);
9011 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9012 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9013 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9014 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9015 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9016 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9017 if (type->baseType != NULL)
9018 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9019 valType));
9020 } else if ((type->subtypes != NULL) &&
9021 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9022 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9023 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9024 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9025 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9026 valType));
9027 }
9028
9029 return (0);
9030}
9031
9032/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009033 * xmlSchemaIsDerivedFromBuiltInType:
9034 * @type: the simpleType definition
9035 *
9036 * Returns the primitive type of the given type or
9037 * NULL in case of error.
9038 */
9039static xmlSchemaTypePtr
9040xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9041{
9042 while (type != NULL) {
9043 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9044 return (type);
9045 type = type->baseType;
9046 }
9047
9048 return (NULL);
9049}
9050
9051
9052/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009053 * xmlSchemaBuildAttributeUsesOwned:
9054 * @ctxt: the schema parser context
9055 * @type: the complex type definition
9056 * @cur: the attribute declaration list
9057 * @lastUse: the top of the attribute use list
9058 *
9059 * Builds the attribute uses list on the given complex type.
9060 * This one is supposed to be called by
9061 * xmlSchemaBuildAttributeValidation only.
9062 */
9063static int
9064xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9065 xmlSchemaAttributePtr cur,
9066 xmlSchemaAttributeLinkPtr *uses,
9067 xmlSchemaAttributeLinkPtr *lastUse)
9068{
9069 xmlSchemaAttributeLinkPtr tmp;
9070 while (cur != NULL) {
9071 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9072 /*
9073 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9074 * to by the ·actual value·s of the ref [attribute] of the
9075 * <attributeGroup> [children], if any."
9076 */
9077 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9078 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9079 lastUse) == -1) {
9080 return (-1);
9081 }
9082 } else {
9083 /* W3C: "1 The set of attribute uses corresponding to the
9084 * <attribute> [children], if any."
9085 */
9086 tmp = (xmlSchemaAttributeLinkPtr)
9087 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9088 if (tmp == NULL) {
9089 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9090 return (-1);
9091 }
9092 tmp->attr = cur;
9093 tmp->next = NULL;
9094 if (*uses == NULL)
9095 *uses = tmp;
9096 else
9097 (*lastUse)->next = tmp;
9098 *lastUse = tmp;
9099 }
9100 cur = cur->next;
9101 }
9102 return (0);
9103}
9104
Daniel Veillard50355f02004-06-08 17:52:16 +00009105/**
9106 * xmlSchemaCloneWildcardNsConstraints:
9107 * @ctxt: the schema parser context
9108 * @dest: the destination wildcard
9109 * @source: the source wildcard
9110 *
9111 * Clones the namespace constraints of source
9112 * and assignes them to dest.
9113 * Returns -1 on internal error, 0 otherwise.
9114 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009115static int
9116xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9117 xmlSchemaWildcardPtr *dest,
9118 xmlSchemaWildcardPtr source)
9119{
9120 xmlSchemaWildcardNsPtr cur, tmp, last;
9121
9122 if ((source == NULL) || (*dest == NULL))
9123 return(-1);
9124 (*dest)->any = source->any;
9125 cur = source->nsSet;
9126 last = NULL;
9127 while (cur != NULL) {
9128 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9129 if (tmp == NULL)
9130 return(-1);
9131 tmp->value = cur->value;
9132 if (last == NULL)
9133 (*dest)->nsSet = tmp;
9134 else
9135 last->next = tmp;
9136 last = tmp;
9137 cur = cur->next;
9138 }
9139 if ((*dest)->negNsSet != NULL)
9140 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9141 if (source->negNsSet != NULL) {
9142 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9143 if ((*dest)->negNsSet == NULL)
9144 return(-1);
9145 (*dest)->negNsSet->value = source->negNsSet->value;
9146 } else
9147 (*dest)->negNsSet = NULL;
9148 return(0);
9149}
9150
Daniel Veillard50355f02004-06-08 17:52:16 +00009151/**
9152 * xmlSchemaUnionWildcards:
9153 * @ctxt: the schema parser context
9154 * @completeWild: the first wildcard
9155 * @curWild: the second wildcard
9156 *
9157 * Unions the namespace constraints of the given wildcards.
9158 * @completeWild will hold the resulting union.
9159 * Returns a positive error code on failure, -1 in case of an
9160 * internal error, 0 otherwise.
9161 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009162static int
9163xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9164 xmlSchemaWildcardPtr completeWild,
9165 xmlSchemaWildcardPtr curWild)
9166{
9167 xmlSchemaWildcardNsPtr cur, curB, tmp;
9168
9169 /*
9170 * 1 If O1 and O2 are the same value, then that value must be the
9171 * value.
9172 */
9173 if ((completeWild->any == curWild->any) &&
9174 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9175 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9176
9177 if ((completeWild->negNsSet == NULL) ||
9178 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9179
9180 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009181 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009182
9183 /*
9184 * Check equality of sets.
9185 */
9186 cur = completeWild->nsSet;
9187 while (cur != NULL) {
9188 found = 0;
9189 curB = curWild->nsSet;
9190 while (curB != NULL) {
9191 if (cur->value == curB->value) {
9192 found = 1;
9193 break;
9194 }
9195 curB = curB->next;
9196 }
9197 if (!found)
9198 break;
9199 cur = cur->next;
9200 }
9201 if (found)
9202 return(0);
9203 } else
9204 return(0);
9205 }
9206 }
9207 /*
9208 * 2 If either O1 or O2 is any, then any must be the value
9209 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009210 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009211 if (completeWild->any == 0) {
9212 completeWild->any = 1;
9213 if (completeWild->nsSet != NULL) {
9214 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9215 completeWild->nsSet = NULL;
9216 }
9217 if (completeWild->negNsSet != NULL) {
9218 xmlFree(completeWild->negNsSet);
9219 completeWild->negNsSet = NULL;
9220 }
9221 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009222 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009223 }
9224 /*
9225 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9226 * then the union of those sets must be the value.
9227 */
9228 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9229 int found;
9230 xmlSchemaWildcardNsPtr start;
9231
9232 cur = curWild->nsSet;
9233 start = completeWild->nsSet;
9234 while (cur != NULL) {
9235 found = 0;
9236 curB = start;
9237 while (curB != NULL) {
9238 if (cur->value == curB->value) {
9239 found = 1;
9240 break;
9241 }
9242 curB = curB->next;
9243 }
9244 if (!found) {
9245 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9246 if (tmp == NULL)
9247 return (-1);
9248 tmp->value = cur->value;
9249 tmp->next = completeWild->nsSet;
9250 completeWild->nsSet = tmp;
9251 }
9252 cur = cur->next;
9253 }
9254
9255 return(0);
9256 }
9257 /*
9258 * 4 If the two are negations of different values (namespace names
9259 * or ·absent·), then a pair of not and ·absent· must be the value.
9260 */
9261 if ((completeWild->negNsSet != NULL) &&
9262 (curWild->negNsSet != NULL) &&
9263 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9264 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009265
9266 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009267 }
9268 /*
9269 * 5.
9270 */
9271 if (((completeWild->negNsSet != NULL) &&
9272 (completeWild->negNsSet->value != NULL) &&
9273 (curWild->nsSet != NULL)) ||
9274 ((curWild->negNsSet != NULL) &&
9275 (curWild->negNsSet->value != NULL) &&
9276 (completeWild->nsSet != NULL))) {
9277
9278 int nsFound, absentFound = 0;
9279
9280 if (completeWild->nsSet != NULL) {
9281 cur = completeWild->nsSet;
9282 curB = curWild->negNsSet;
9283 } else {
9284 cur = curWild->nsSet;
9285 curB = completeWild->negNsSet;
9286 }
9287 nsFound = 0;
9288 while (cur != NULL) {
9289 if (cur->value == NULL)
9290 absentFound = 1;
9291 else if (cur->value == curB->value)
9292 nsFound = 1;
9293 if (nsFound && absentFound)
9294 break;
9295 cur = cur->next;
9296 }
9297
9298 if (nsFound && absentFound) {
9299 /*
9300 * 5.1 If the set S includes both the negated namespace
9301 * name and ·absent·, then any must be the value.
9302 */
9303 completeWild->any = 1;
9304 if (completeWild->nsSet != NULL) {
9305 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9306 completeWild->nsSet = NULL;
9307 }
9308 if (completeWild->negNsSet != NULL) {
9309 xmlFree(completeWild->negNsSet);
9310 completeWild->negNsSet = NULL;
9311 }
9312 } else if (nsFound && (!absentFound)) {
9313 /*
9314 * 5.2 If the set S includes the negated namespace name
9315 * but not ·absent·, then a pair of not and ·absent· must
9316 * be the value.
9317 */
9318 if (completeWild->nsSet != NULL) {
9319 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9320 completeWild->nsSet = NULL;
9321 }
9322 if (completeWild->negNsSet == NULL) {
9323 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9324 if (completeWild->negNsSet == NULL)
9325 return (-1);
9326 }
9327 completeWild->negNsSet->value = NULL;
9328 } else if ((!nsFound) && absentFound) {
9329 /*
9330 * 5.3 If the set S includes ·absent· but not the negated
9331 * namespace name, then the union is not expressible.
9332 */
9333 xmlSchemaPErr(ctxt, completeWild->node,
9334 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009335 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009336 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009337 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009338 } else if ((!nsFound) && (!absentFound)) {
9339 /*
9340 * 5.4 If the set S does not include either the negated namespace
9341 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9342 * and a namespace name must be the value.
9343 */
9344 if (completeWild->negNsSet == NULL) {
9345 if (completeWild->nsSet != NULL) {
9346 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9347 completeWild->nsSet = NULL;
9348 }
9349 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9350 if (completeWild->negNsSet == NULL)
9351 return (-1);
9352 completeWild->negNsSet->value = curWild->negNsSet->value;
9353 }
9354 }
9355 return (0);
9356 }
9357 /*
9358 * 6.
9359 */
9360 if (((completeWild->negNsSet != NULL) &&
9361 (completeWild->negNsSet->value == NULL) &&
9362 (curWild->nsSet != NULL)) ||
9363 ((curWild->negNsSet != NULL) &&
9364 (curWild->negNsSet->value == NULL) &&
9365 (completeWild->nsSet != NULL))) {
9366
9367 if (completeWild->nsSet != NULL) {
9368 cur = completeWild->nsSet;
9369 } else {
9370 cur = curWild->nsSet;
9371 }
9372 while (cur != NULL) {
9373 if (cur->value == NULL) {
9374 /*
9375 * 6.1 If the set S includes ·absent·, then any must be the
9376 * value.
9377 */
9378 completeWild->any = 1;
9379 if (completeWild->nsSet != NULL) {
9380 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9381 completeWild->nsSet = NULL;
9382 }
9383 if (completeWild->negNsSet != NULL) {
9384 xmlFree(completeWild->negNsSet);
9385 completeWild->negNsSet = NULL;
9386 }
9387 return (0);
9388 }
9389 cur = cur->next;
9390 }
9391 if (completeWild->negNsSet == NULL) {
9392 /*
9393 * 6.2 If the set S does not include ·absent·, then a pair of not
9394 * and ·absent· must be the value.
9395 */
9396 if (completeWild->nsSet != NULL) {
9397 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9398 completeWild->nsSet = NULL;
9399 }
9400 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9401 if (completeWild->negNsSet == NULL)
9402 return (-1);
9403 completeWild->negNsSet->value = NULL;
9404 }
9405 return (0);
9406 }
9407 return (0);
9408
9409}
9410
Daniel Veillard50355f02004-06-08 17:52:16 +00009411/**
9412 * xmlSchemaIntersectWildcards:
9413 * @ctxt: the schema parser context
9414 * @completeWild: the first wildcard
9415 * @curWild: the second wildcard
9416 *
9417 * Intersects the namespace constraints of the given wildcards.
9418 * @completeWild will hold the resulting intersection.
9419 * Returns a positive error code on failure, -1 in case of an
9420 * internal error, 0 otherwise.
9421 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009422static int
9423xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9424 xmlSchemaWildcardPtr completeWild,
9425 xmlSchemaWildcardPtr curWild)
9426{
William M. Brack803812b2004-06-03 02:11:24 +00009427 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009428
9429 /*
9430 * 1 If O1 and O2 are the same value, then that value must be the
9431 * value.
9432 */
9433 if ((completeWild->any == curWild->any) &&
9434 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9435 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9436
9437 if ((completeWild->negNsSet == NULL) ||
9438 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9439
9440 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009441 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009442
9443 /*
9444 * Check equality of sets.
9445 */
9446 cur = completeWild->nsSet;
9447 while (cur != NULL) {
9448 found = 0;
9449 curB = curWild->nsSet;
9450 while (curB != NULL) {
9451 if (cur->value == curB->value) {
9452 found = 1;
9453 break;
9454 }
9455 curB = curB->next;
9456 }
9457 if (!found)
9458 break;
9459 cur = cur->next;
9460 }
9461 if (found)
9462 return(0);
9463 } else
9464 return(0);
9465 }
9466 }
9467 /*
9468 * 2 If either O1 or O2 is any, then the other must be the value.
9469 */
9470 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9471 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9472 return(-1);
9473 return(0);
9474 }
9475 /*
9476 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9477 * name or ·absent·) and the other is a set of (namespace names or
9478 * ·absent·), then that set, minus the negated value if it was in
9479 * the set, minus ·absent· if it was in the set, must be the value.
9480 */
9481 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9482 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9483 const xmlChar *neg;
9484
9485 if (completeWild->nsSet == NULL) {
9486 neg = completeWild->negNsSet->value;
9487 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9488 return(-1);
9489 } else
9490 neg = curWild->negNsSet->value;
9491 /*
9492 * Remove absent and negated.
9493 */
9494 prev = NULL;
9495 cur = completeWild->nsSet;
9496 while (cur != NULL) {
9497 if (cur->value == NULL) {
9498 if (prev == NULL)
9499 completeWild->nsSet = cur->next;
9500 else
9501 prev->next = cur->next;
9502 xmlFree(cur);
9503 break;
9504 }
9505 prev = cur;
9506 cur = cur->next;
9507 }
9508 if (neg != NULL) {
9509 prev = NULL;
9510 cur = completeWild->nsSet;
9511 while (cur != NULL) {
9512 if (cur->value == neg) {
9513 if (prev == NULL)
9514 completeWild->nsSet = cur->next;
9515 else
9516 prev->next = cur->next;
9517 xmlFree(cur);
9518 break;
9519 }
9520 prev = cur;
9521 cur = cur->next;
9522 }
9523 }
9524
9525 return(0);
9526 }
9527 /*
9528 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9529 * then the intersection of those sets must be the value.
9530 */
9531 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9532 int found;
9533
9534 cur = completeWild->nsSet;
9535 prev = NULL;
9536 while (cur != NULL) {
9537 found = 0;
9538 curB = curWild->nsSet;
9539 while (curB != NULL) {
9540 if (cur->value == curB->value) {
9541 found = 1;
9542 break;
9543 }
9544 curB = curB->next;
9545 }
9546 if (!found) {
9547 if (prev == NULL)
9548 completeWild->nsSet = cur->next;
9549 else
9550 prev->next = cur->next;
9551 tmp = cur->next;
9552 xmlFree(cur);
9553 cur = tmp;
9554 continue;
9555 }
9556 prev = cur;
9557 cur = cur->next;
9558 }
9559
9560 return(0);
9561 }
9562 /* 5 If the two are negations of different namespace names,
9563 * then the intersection is not expressible
9564 */
9565 if ((completeWild->negNsSet != NULL) &&
9566 (curWild->negNsSet != NULL) &&
9567 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9568 (completeWild->negNsSet->value != NULL) &&
9569 (curWild->negNsSet->value != NULL)) {
9570
9571 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009572 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009573 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009574 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009575 }
9576 /*
9577 * 6 If the one is a negation of a namespace name and the other
9578 * is a negation of ·absent·, then the one which is the negation
9579 * of a namespace name must be the value.
9580 */
9581 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9582 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9583 (completeWild->negNsSet->value == NULL)) {
9584 completeWild->negNsSet->value = curWild->negNsSet->value;
9585 }
9586 return(0);
9587}
9588
Daniel Veillard50355f02004-06-08 17:52:16 +00009589/**
9590 * xmlSchemaIsWildcardNsConstraintSubset:
9591 * @ctxt: the schema parser context
9592 * @wildA: the first wildcard
9593 * @wildB: the second wildcard
9594 *
9595 * Returns 1 if the namespace constraint of @wildA is an intensional
9596 * subset of @wildB, 0 otherwise.
9597 */
9598static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009599xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9600 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009601{
Daniel Veillard3646d642004-06-02 19:19:14 +00009602
Daniel Veillard50355f02004-06-08 17:52:16 +00009603 /*
9604 * Schema Component Constraint: Wildcard Subset
9605 */
9606 /*
9607 * 1 super must be any.
9608 */
9609 if (wildB->any)
9610 return (1);
9611 /*
9612 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9613 * 2.2 super must be a pair of not and the same value.
9614 */
9615 if ((wildA->negNsSet != NULL) &&
9616 (wildB->negNsSet != NULL) &&
9617 (wildA->negNsSet->value == wildA->negNsSet->value))
9618 return (1);
9619 /*
9620 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9621 */
9622 if (wildA->nsSet != NULL) {
9623 /*
9624 * 3.2.1 super must be the same set or a superset thereof.
9625 */
9626 if (wildB->nsSet != NULL) {
9627 xmlSchemaWildcardNsPtr cur, curB;
9628 int found = 0;
9629
9630 cur = wildA->nsSet;
9631 while (cur != NULL) {
9632 found = 0;
9633 curB = wildB->nsSet;
9634 while (curB != NULL) {
9635 if (cur->value == curB->value) {
9636 found = 1;
9637 break;
9638 }
9639 curB = curB->next;
9640 }
9641 if (!found)
9642 return (0);
9643 cur = cur->next;
9644 }
9645 if (found)
9646 return (1);
9647 } else if (wildB->negNsSet != NULL) {
9648 xmlSchemaWildcardNsPtr cur;
9649 /*
9650 * 3.2.2 super must be a pair of not and a namespace name or
9651 * ·absent· and that value must not be in sub's set.
9652 */
9653 cur = wildA->nsSet;
9654 while (cur != NULL) {
9655 if (cur->value == wildB->negNsSet->value)
9656 return (0);
9657 cur = cur->next;
9658 }
9659 return (1);
9660 }
9661 }
9662 return (0);
9663}
9664
9665/**
9666 * xmlSchemaBuildCompleteAttributeWildcard:
9667 * @ctxt: the schema parser context
9668 * @attrs: the attribute list
9669 * @completeWild: the resulting complete wildcard
9670 *
9671 * Returns -1 in case of an internal error, 0 otherwise.
9672 */
9673static int
9674xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9675 xmlSchemaAttributePtr attrs,
9676 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009677{
9678 while (attrs != NULL) {
9679 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9680 xmlSchemaAttributeGroupPtr group;
9681
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009682 group = (xmlSchemaAttributeGroupPtr) attrs;
9683 /*
9684 * Handle attribute group references.
9685 */
9686 if (group->ref != NULL) {
9687 if (group->refItem == NULL) {
9688 /*
9689 * TODO: Should we raise a warning here?
9690 */
9691 /*
9692 * The referenced attribute group definition could not
9693 * be resolved beforehand, so skip.
9694 */
9695 attrs = attrs->next;
9696 continue;
9697 } else
9698 group = group->refItem;
9699 }
9700 /*
9701 * For every attribute group definition, an intersected wildcard
9702 * will be created (assumed that a wildcard exists on the
9703 * particular attr. gr. def. or on any contained attr. gr. def
9704 * at all).
9705 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9706 * that the intersection will be performed only once.
9707 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009708 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9709 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009710 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9711 group->attributes, &group->attributeWildcard) == -1)
9712 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009713 }
9714 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9715 }
9716 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009717 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009718 /*
9719 * Copy the first encountered wildcard as context, except for the annotation.
9720 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009721 *completeWild = xmlSchemaAddWildcard(ctxt);
9722 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9723 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9724 completeWild, group->attributeWildcard) == -1)
9725 return (-1);
9726 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009727 /*
9728 * Although the complete wildcard might not correspond to any
9729 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009730 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009731 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009732 (*completeWild)->node = group->attributeWildcard->node;
9733
9734 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9735 xmlSchemaFreeWildcard(*completeWild);
9736 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009737 }
9738 }
9739 }
9740 attrs = attrs->next;
9741 }
9742
Daniel Veillard50355f02004-06-08 17:52:16 +00009743 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009744}
9745
9746/**
9747 * xmlSchemaMatchesWildcardNs:
9748 * @wild: the wildcard
9749 * @ns: the namespace
9750 *
9751 *
9752 * Returns 1 if the given namespace matches the wildcard,
9753 * 0 otherwise.
9754 */
9755static int
9756xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
9757{
9758 if (wild == NULL)
9759 return(0);
9760
9761 if (wild->any)
9762 return(1);
9763 else if (wild->nsSet != NULL) {
9764 xmlSchemaWildcardNsPtr cur;
9765
9766 cur = wild->nsSet;
9767 while (cur != NULL) {
9768 if (xmlStrEqual(cur->value, ns))
9769 return(1);
9770 cur = cur->next;
9771 }
9772 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
9773 (!xmlStrEqual(wild->negNsSet->value, ns)))
9774 return(1);
9775
9776 return(0);
9777}
9778
9779/**
9780 * xmlSchemaBuildAttributeValidation:
9781 * @ctxt: the schema parser context
9782 * @type: the complex type definition
9783 *
9784 *
9785 * Builds the wildcard and the attribute uses on the given complex type.
9786 * Returns -1 if an internal error occurs, 0 otherwise.
9787 */
9788static int
9789xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
9790{
9791 xmlSchemaTypePtr baseType = NULL;
9792 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +00009793 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00009794 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009795 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +00009796 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009797 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009798 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009799
Daniel Veillard01fa6152004-06-29 17:04:39 +00009800 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009801 /*
9802 * Complex Type Definition with complex content Schema Component.
9803 *
9804 * Attribute uses.
9805 */
9806 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009807 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009808 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +00009809 "attribute uses already builded.\n",
9810 NULL, NULL);
9811 return (-1);
9812 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009813 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009814 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009815 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +00009816 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00009817 type->name, NULL);
9818 return (-1);
9819 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009820 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009821 if (baseType == anyType)
9822 baseIsAnyType = 1;
9823 /*
9824 * Inherit the attribute uses of the base type.
9825 */
9826 /*
9827 * NOTE: It is allowed to "extend" the anyType complex type.
9828 */
9829 if (!baseIsAnyType) {
9830 if (baseType != NULL) {
9831 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
9832 tmp = (xmlSchemaAttributeLinkPtr)
9833 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9834 if (tmp == NULL) {
9835 xmlSchemaPErrMemory(ctxt,
9836 "building attribute uses of complexType", NULL);
9837 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009838 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009839 tmp->attr = cur->attr;
9840 tmp->next = NULL;
9841 if (type->attributeUses == NULL) {
9842 type->attributeUses = tmp;
9843 } else
9844 lastBaseUse->next = tmp;
9845 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009846 }
9847 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009848 }
9849 if ((type->subtypes != NULL) &&
9850 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9851 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009852 /*
9853 * type --> (<simpleContent>|<complexContent>)
9854 * --> (<restriction>|<extension>) --> attributes
9855 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009856 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009857 } else {
9858 /* Short hand form of the complexType. */
9859 attrs = type->attributes;
9860 }
9861 /*
9862 * Handle attribute wildcards.
9863 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009864 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9865 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009866 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009867 * NOTE: During the parse time, the wildcard is created on the complexType
9868 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009869 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009870 if (err == -1) {
9871 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
9872 "Internal error: xmlSchemaBuildAttributeValidation: "
9873 "failed to build an intersected attribute wildcard.\n",
9874 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009875 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009876 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009877
9878 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
9879 ((baseIsAnyType) ||
9880 ((baseType != NULL) &&
9881 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
9882 (baseType->attributeWildcard != NULL)))) {
9883 if (type->attributeWildcard != NULL) {
9884 /*
9885 * Union the complete wildcard with the base wildcard.
9886 */
9887 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
9888 baseType->attributeWildcard) == -1)
9889 return (-1);
9890 } else {
9891 /*
9892 * Just inherit the wildcard.
9893 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009894 /*
9895 * NOTE: This is the only case where an attribute
9896 * wildcard is shared.
9897 */
9898 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
9899 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009900 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +00009901 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009902 }
9903
9904 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
9905 if (type->attributeWildcard != NULL) {
9906 /*
9907 * Derivation Valid (Restriction, Complex)
9908 * 4.1 The {base type definition} must also have one.
9909 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009910 if (baseType->attributeWildcard == NULL) {
9911 xmlSchemaPCustomErr(ctxt,
9912 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
9913 NULL, type, NULL,
9914 "The type has an attribute wildcard, "
9915 "but the base type %s does not have one",
9916 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9917 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009918 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009919 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009920 type->attributeWildcard, baseType->attributeWildcard) == 0) {
9921 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009922 xmlSchemaPCustomErr(ctxt,
9923 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
9924 NULL, type, NULL,
9925 "The attribute wildcard is not a valid "
9926 "subset of the wildcard in the base type %s",
9927 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9928 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009929 return (1);
9930 }
9931 /* 4.3 Unless the {base type definition} is the ·ur-type
9932 * definition·, the complex type definition's {attribute
9933 * wildcard}'s {process contents} must be identical to or
9934 * stronger than the {base type definition}'s {attribute
9935 * wildcard}'s {process contents}, where strict is stronger
9936 * than lax is stronger than skip.
9937 */
9938 if ((type->baseType != anyType) &&
9939 (type->attributeWildcard->processContents <
9940 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009941 xmlSchemaPCustomErr(ctxt,
9942 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
9943 NULL, type, NULL,
9944 "The 'process contents' of the attribute wildcard is weaker than "
9945 "the one in the base type %s",
9946 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9947 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009948 return (1);
9949 }
9950 }
9951 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
9952 /*
9953 * Derivation Valid (Extension)
9954 * At this point the type and the base have both, either
9955 * no wildcard or a wildcard.
9956 */
9957 if ((baseType->attributeWildcard != NULL) &&
9958 (baseType->attributeWildcard != type->attributeWildcard)) {
9959 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009960 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009961 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009962 xmlSchemaPCustomErr(ctxt,
9963 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
9964 NULL, type, NULL,
9965 "The attribute wildcard is not a valid "
9966 "superset of the one in the base type %s",
9967 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
9968 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009969 return (1);
9970 }
9971 }
9972 }
9973
Daniel Veillard3646d642004-06-02 19:19:14 +00009974 /*
9975 * Gather attribute uses defined by this type.
9976 */
9977 if (attrs != NULL) {
9978 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
9979 &uses, &lastUse) == -1) {
9980 return (-1);
9981 }
9982 }
9983 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
9984 * "Two distinct attribute declarations in the {attribute uses} must
9985 * not have identical {name}s and {target namespace}s."
9986 *
9987 * For "extension" this is done further down.
9988 */
9989 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
9990 cur = uses;
9991 while (cur != NULL) {
9992 tmp = cur->next;
9993 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009994 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
9995 xmlSchemaGetAttrName(tmp->attr))) &&
9996 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
9997 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
9998
9999 xmlSchemaPAttrUseErr(ctxt,
10000 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10001 NULL, type, NULL, cur->attr,
10002 "Duplicate attribute use %s specified",
10003 xmlSchemaFormatNsUriLocal(&str,
10004 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10005 xmlSchemaGetAttrName(tmp->attr))
10006 );
10007 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010008 break;
10009 }
10010 tmp = tmp->next;
10011 }
10012 cur = cur->next;
10013 }
10014 }
10015 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10016 /*
10017 * Derive by restriction.
10018 */
10019 if (baseIsAnyType) {
10020 type->attributeUses = uses;
10021 } else {
10022 int found;
10023
10024 cur = uses;
10025 while (cur != NULL) {
10026 found = 0;
10027 base = type->attributeUses;
10028 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010029 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10030 xmlSchemaGetAttrName(base->attr)) &&
10031 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10032 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010033
Daniel Veillardc0826a72004-08-10 14:17:33 +000010034 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000010035 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10036 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10037 /*
10038 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010039 */
10040 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010041 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010042 NULL, type, NULL, cur->attr,
10043 "The 'optional' use is inconsistent with a matching "
10044 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010045 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10046 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10047 /*
10048 * derivation-ok-restriction 3
10049 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010050 xmlSchemaPCustomErr(ctxt,
10051 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10052 NULL, type, NULL,
10053 "A matching attribute use for the 'required' "
10054 "attribute use %s of the base type is missing",
10055 xmlSchemaFormatNsUriLocal(&str,
10056 xmlSchemaGetAttrTargetNsURI(base->attr),
10057 xmlSchemaGetAttrName(base->attr)));
10058 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010059 } else {
10060 /*
10061 * Override the attribute use.
10062 */
10063 base->attr = cur->attr;
10064 }
10065 /*
10066 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
Daniel Veillard50355f02004-06-08 17:52:16 +000010067 * TODO: derivation-ok-restriction 2.1.3
Daniel Veillard3646d642004-06-02 19:19:14 +000010068 */
10069 break;
10070 }
10071 base = base->next;
10072 }
10073
10074 if (!found) {
10075 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10076 /*
10077 * derivation-ok-restriction 2.2
10078 */
10079 if ((type->attributeWildcard != NULL) &&
10080 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10081 cur->attr->targetNamespace))
10082 found = 1;
10083
10084 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010085 xmlSchemaPAttrUseErr(ctxt,
10086 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10087 NULL, type, NULL, cur->attr,
10088 "Neither a matching attribute use, "
10089 "nor a matching wildcard in the base type does exist",
10090 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010091 } else {
10092 /*
10093 * Add the attribute use.
10094 *
10095 * Note that this may lead to funny derivation error reports, if
10096 * multiple equal attribute uses exist; but this is not
10097 * allowed anyway, and it will be reported beforehand.
10098 */
10099 tmp = cur;
10100 if (prev != NULL)
10101 prev->next = cur->next;
10102 else
10103 uses = cur->next;
10104 cur = cur->next;
10105 if (type->attributeUses == NULL) {
10106 type->attributeUses = tmp;
10107 } else
10108 lastBaseUse->next = tmp;
10109 lastBaseUse = tmp;
10110
10111 continue;
10112 }
10113 }
10114 }
10115 prev = cur;
10116 cur = cur->next;
10117 }
10118 if (uses != NULL)
10119 xmlSchemaFreeAttributeUseList(uses);
10120 }
10121 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10122 /*
10123 * The spec allows only appending, and not other kinds of extensions.
10124 *
10125 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10126 */
10127 if (uses != NULL) {
10128 if (type->attributeUses == NULL) {
10129 type->attributeUses = uses;
10130 } else
10131 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010132 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010133 } else {
10134 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010135 * Derive implicitely from the ur-type.
10136 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010137 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010138 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010139 /*
10140 * 3.4.6 -> Complex Type Definition Properties Correct
10141 */
10142 if (type->attributeUses != NULL) {
10143 cur = type->attributeUses;
10144 prev = NULL;
10145 while (cur != NULL) {
10146 /*
10147 * 4. Two distinct attribute declarations in the {attribute uses} must
10148 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010149 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010150 * Note that this was already done for "restriction" and types derived from
10151 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010152 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010153 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10154 tmp = cur->next;
10155 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010156 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10157 xmlSchemaGetAttrName(tmp->attr))) &&
10158 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10159 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010160
Daniel Veillardc0826a72004-08-10 14:17:33 +000010161 xmlSchemaPAttrUseErr(ctxt,
10162 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10163 NULL, type, NULL, tmp->attr,
10164 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010165 break;
10166 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010167 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010168 }
10169 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010170 /*
10171 * 5. Two distinct attribute declarations in the {attribute uses} must
10172 * not have {type definition}s which are or are derived from ID.
10173 */
10174 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010175 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010176 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010177 xmlSchemaPAttrUseErr(ctxt,
10178 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10179 NULL, type, NULL, cur->attr,
10180 "There must not exist more than one attribute use, "
10181 "declared of type 'ID' or derived from it",
10182 NULL);
10183 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010184 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010185 id = cur;
10186 }
10187 /*
10188 * Remove "prohibited" attribute uses. The reason this is done at this late
10189 * stage is to be able to catch dublicate attribute uses. So we had to keep
10190 * prohibited uses in the list as well.
10191 */
10192 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10193 tmp = cur;
10194 if (prev == NULL)
10195 type->attributeUses = cur->next;
10196 else
10197 prev->next = cur->next;
10198 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010199 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010200 } else {
10201 prev = cur;
10202 cur = cur->next;
10203 }
10204 }
10205 }
10206 /*
10207 * TODO: This check should be removed if we are 100% sure of
10208 * the base type attribute uses already being built.
10209 */
10210 if ((baseType != NULL) && (!baseIsAnyType) &&
10211 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10212 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010213 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010214 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010215 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010216 baseType->name, NULL);
10217 }
10218 return (0);
10219}
10220
10221/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010222 * xmlSchemaTypeFinalContains:
10223 * @schema: the schema
10224 * @type: the type definition
10225 * @final: the final
10226 *
10227 * Evaluates if a type definition contains the given "final".
10228 * This does take "finalDefault" into account as well.
10229 *
10230 * Returns 1 if the type does containt the given "final",
10231 * 0 otherwise.
10232 */
10233static int
10234xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10235{
10236 int tfinal = final, tflags = type->flags;
10237
10238 if (type == NULL)
10239 return (0);
10240 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10241 switch (final) {
10242 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10243 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10244 break;
10245 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10246 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10247 break;
10248 case XML_SCHEMAS_TYPE_FINAL_LIST:
10249 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10250 break;
10251 case XML_SCHEMAS_TYPE_FINAL_UNION:
10252 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10253 break;
10254 }
10255 tflags = schema->flags;
10256 }
10257 if (tflags & tfinal)
10258 return (1);
10259 else
10260 return (0);
10261
10262}
10263
10264/**
10265 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10266 * @type: the Union Simple Type
10267 *
10268 * Returns a list of member types of @type if existing,
10269 * returns NULL otherwise.
10270 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010271static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010272xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10273{
10274 while (type != NULL) {
10275 if (type->memberTypes != NULL)
10276 return (type->memberTypes);
10277 else
10278 type = type->baseType;
10279 }
10280 return (NULL);
10281}
10282
10283/**
10284 * xmlSchemaGetListSimpleTypeItemType:
10285 * @type: the simple type definition
10286 *
10287 * Returns the item type definition of the list simple type.
10288 */
10289static xmlSchemaTypePtr
10290xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10291{
10292 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10293 return (NULL);
10294 /*
10295 * Note: In libxml2, the built-in types do not reflect
10296 * the datatype hierarchy (yet?) - we have to treat them
10297 * in a special way.
10298 */
10299 if (type->type == XML_SCHEMA_TYPE_BASIC)
10300 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10301 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10302 /* 1 If the <list> alternative is chosen, then the type
10303 * definition ·resolved· to by the ·actual value· of the
10304 * itemType [attribute] of <list>, if present, otherwise
10305 * the type definition corresponding to the <simpleType>
10306 * among the [children] of <list>.
10307 */
10308 return (type->subtypes->subtypes);
10309 else {
10310 /* 2 If the <restriction> option is chosen, then the
10311 * {item type definition} of the {base type definition}.
10312 */
10313 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10314 }
10315}
10316
10317/**
10318 * xmlSchemaCheckCOSSTDerivedOK:
10319 * @type: the derived simple type definition
10320 * @baseType: the base type definition
10321 *
10322 * Checks wheter @type can be validly
10323 * derived from @baseType.
10324 *
10325 * Returns 0 on success, an positive error code otherwise.
10326 */
10327static int
10328xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10329 xmlSchemaTypePtr type,
10330 xmlSchemaTypePtr baseType,
10331 int subset)
10332{
10333 /*
10334 * Schema Component Constraint: Type Derivation OK (Simple)
10335 *
10336 *
10337 * 1 They are the same type definition.
10338 * TODO: The identy check might have to be more complex than this.
10339 */
10340 if (type == baseType)
10341 return (0);
10342 /*
10343 * 2.1 restriction is not in the subset, or in the {final}
10344 * of its own {base type definition};
10345 */
10346 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10347 (xmlSchemaTypeFinalContains(schema,
10348 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10349 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10350 }
10351 /* 2.2 */
10352 if (type->baseType == baseType) {
10353 /*
10354 * 2.2.1 D's ·base type definition· is B.
10355 */
10356 return (0);
10357 }
10358 /*
10359 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10360 * and is validly derived from B given the subset, as defined by this
10361 * constraint.
10362 */
10363 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10364 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10365 return (0);
10366 }
10367 /*
10368 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10369 * definition·.
10370 */
10371 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10372 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10373 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10374 return (0);
10375 }
10376 /*
10377 * 2.2.4 B's {variety} is union and D is validly derived from a type
10378 * definition in B's {member type definitions} given the subset, as
10379 * defined by this constraint.
10380 *
10381 * NOTE: This seems not to involve built-in types, since there is no
10382 * built-in Union Simple Type.
10383 */
10384 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10385 xmlSchemaTypeLinkPtr cur;
10386
10387 cur = baseType->memberTypes;
10388 while (cur != NULL) {
10389 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10390 cur->type, subset) == 0)
10391 return (0);
10392 cur = cur->next;
10393 }
10394 }
10395
10396 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10397}
10398
10399
10400/**
10401 * xmlSchemaCheckSTPropsCorrect:
10402 * @ctxt: the schema parser context
10403 * @type: the simple type definition
10404 *
10405 * Checks st-props-correct.
10406 *
10407 * Returns 0 if the properties are correct,
10408 * if not, a positive error code and -1 on internal
10409 * errors.
10410 */
10411static int
10412xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10413 xmlSchemaTypePtr type)
10414{
10415 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10416 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010417 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010418
Daniel Veillardc0826a72004-08-10 14:17:33 +000010419 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010420 /*
10421 * Schema Component Constraint: Simple Type Definition Properties Correct
10422 *
10423 * NOTE: This is somehow redundant, since we actually built a simple type
10424 * to have all the needed information; this acts as an self test.
10425 */
10426 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10427 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10428 /*
10429 * TODO: 1 The values of the properties of a simple type definition must be as
10430 * described in the property tableau in Datatype definition, modulo the
10431 * impact of Missing Sub-components (§5.3).
10432 */
10433 /* Base type: If the datatype has been ·derived· by ·restriction·
10434 * then the Simple Type Definition component from which it is ·derived·,
10435 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10436 */
10437 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010438 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010439 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010440 NULL, type, NULL,
10441 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010442 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10443 }
10444 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10445 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10446 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010447 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010448 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010449 NULL, type, NULL,
10450 "The base type %s is not a simple type",
10451 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10452 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010453 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10454 }
10455 if ((baseType != anySimpleType) &&
10456 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010457 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010458 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010459 NULL, type, NULL,
10460 "A type, derived by list or union, must have"
10461 "the simple ur-type definition as base type, not %s",
10462 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10463 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010464 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10465 }
10466 /*
10467 * Variety: One of {atomic, list, union}.
10468 */
10469 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10470 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10471 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010472 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010473 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010474 NULL, type, NULL,
10475 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010476 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10477 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010478 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010479
10480 /*
10481 * 2 All simple type definitions must be derived ultimately from the ·simple
10482 * ur-type definition (so· circular definitions are disallowed). That is, it
10483 * must be possible to reach a built-in primitive datatype or the ·simple
10484 * ur-type definition· by repeatedly following the {base type definition}.
10485 */
10486 baseType = type->baseType;
10487 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10488 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10489 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10490 if (baseType == anySimpleType)
10491 break;
10492 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010493 xmlSchemaPCustomErr(ctxt,
10494 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10495 NULL, type, NULL,
10496 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010497 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10498 }
10499 baseType = baseType->baseType;
10500 }
10501 /*
10502 * 3 The {final} of the {base type definition} must not contain restriction.
10503 */
10504 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10505 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010506 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010507 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010508 NULL, type, NULL,
10509 "The 'final' of its base type %s must not contain "
10510 "'restriction'",
10511 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10512 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010513 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10514 }
10515 return (0);
10516}
10517
10518/**
10519 * xmlSchemaCheckDerivationValidSimpleRestriction:
10520 * @ctxt: the schema parser context
10521 * @type: the simple type definition
10522 *
10523 * Checks if the given @type (simpleType) is derived
10524 * validly by restriction.
10525 *
10526 * Returns -1 on internal errors, 0 if the type is validly derived,
10527 * a positive error code otherwise.
10528 */
10529static int
10530xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010531 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010532{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010533 xmlChar *str = NULL;
10534
10535 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010536
10537 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10538 xmlSchemaPErr(ctxt, type->node,
10539 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010540 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10541 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010542 type->name, NULL);
10543 return (-1);
10544 }
10545
10546 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10547 xmlSchemaTypePtr primitive;
10548 /*
10549 * 1.1 The {base type definition} must be an atomic simple
10550 * type definition or a built-in primitive datatype.
10551 */
10552 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010553 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010554 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010555 NULL, type, NULL,
10556 "The base type %s is not an atomic simple type",
10557 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10558 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010559 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10560 }
10561 /* 1.2 The {final} of the {base type definition} must not contain
10562 * restriction.
10563 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010564 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010565 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10566 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010567 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010568 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010569 NULL, type, NULL,
10570 "The final of its base type %s must not contain 'restriction'",
10571 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10572 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10574 }
10575
10576 /*
10577 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10578 * type definition}, as specified in the appropriate subsection of 3.2
10579 * Primitive datatypes.
10580 */
10581 if (type->facets != NULL) {
10582 xmlSchemaFacetPtr facet;
10583 int ok = 1;
10584
10585 primitive = xmlSchemaGetPrimitiveType(type);
10586 if (primitive == NULL) {
10587 xmlSchemaPErr(ctxt, type->node,
10588 XML_ERR_INTERNAL_ERROR,
10589 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010590 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010591 type->name, NULL);
10592 return (-1);
10593 }
10594 facet = type->facets;
10595 do {
10596 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010597 ok = 0;
10598 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010599 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010600 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010601 }
10602 facet = facet->next;
10603 } while (facet != NULL);
10604 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010605 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010606 }
10607 /*
10608 * TODO: 1.3.2 (facet derivation)
10609 */
10610 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10611 xmlSchemaTypePtr itemType = NULL;
10612
10613 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10614 if (itemType == NULL) {
10615 xmlSchemaPErr(ctxt, type->node,
10616 XML_ERR_INTERNAL_ERROR,
10617 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010618 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010619 type->name, NULL);
10620 return (-1);
10621 }
10622 /*
10623 * 2.1 The {item type definition} must have a {variety} of atomic or
10624 * union (in which case all the {member type definitions}
10625 * must be atomic).
10626 */
10627 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10628 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010629 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010630 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010631 NULL, type, NULL,
10632 "The item type %s must have a variety of atomic or union",
10633 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10634 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010635 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10636 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10637 xmlSchemaTypeLinkPtr member;
10638
10639 member = itemType->memberTypes;
10640 while (member != NULL) {
10641 if ((member->type->flags &
10642 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010643 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010644 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010645 NULL, type, NULL,
10646 "The item type is a union type, but the "
10647 "member type %s of this item type is not atomic",
10648 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10649 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010650 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10651 }
10652 member = member->next;
10653 }
10654 }
10655
10656 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10657 xmlSchemaFacetPtr facet;
10658 /*
10659 * This is the case if we have: <simpleType><list ..
10660 */
10661 /*
10662 * 2.3.1
10663 * 2.3.1.1 The {final} of the {item type definition} must not
10664 * contain list.
10665 */
10666 if (xmlSchemaTypeFinalContains(ctxt->schema,
10667 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010668 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010669 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010670 NULL, type, NULL,
10671 "The final of its item type %s must not contain 'list'",
10672 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10673 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010674 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10675 }
10676 /*
10677 * 2.3.1.2 The {facets} must only contain the whiteSpace
10678 * facet component.
10679 */
10680 if (type->facets != NULL) {
10681 facet = type->facets;
10682 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010683 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10684 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010685 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010686 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010687 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10688 }
10689 facet = facet->next;
10690 } while (facet != NULL);
10691 }
10692 /*
10693 * TODO: Datatypes states:
10694 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10695 * whose ·lexical space· allows space (such as string or anyURI)or
10696 * a ·union· datatype any of whose {member type definitions}'s
10697 * ·lexical space· allows space.
10698 */
10699 } else {
10700 /*
10701 * This is the case if we have: <simpleType><restriction ...
10702 */
10703 /*
10704 * 2.3.2
10705 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10706 */
10707 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010708 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010709 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010710 NULL, type, NULL,
10711 "The base type %s must be a list type",
10712 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10713 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010714 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
10715 }
10716 /*
10717 * 2.3.2.2 The {final} of the {base type definition} must not
10718 * contain restriction.
10719 */
10720 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10721 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010722 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010723 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010724 NULL, type, NULL,
10725 "The final of the base type %s must not contain 'restriction'",
10726 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10727 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010728 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
10729 }
10730 /*
10731 * 2.3.2.3 The {item type definition} must be validly derived
10732 * from the {base type definition}'s {item type definition} given
10733 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
10734 */
10735 {
10736 xmlSchemaTypePtr baseItemType;
10737
10738 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
10739 if (baseItemType == NULL) {
10740 xmlSchemaPErr(ctxt, type->node,
10741 XML_ERR_INTERNAL_ERROR,
10742 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010743 "List simple type '%s': Failed to "
10744 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010745 type->name, type->baseType->name);
10746 return (-1);
10747 }
10748 if ((itemType != baseItemType) &&
10749 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
10750 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010751 xmlChar *strBIT = NULL, *strBT = NULL;
10752 xmlSchemaPCustomErrExt(ctxt,
10753 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
10754 NULL, type, NULL,
10755 "The item type %s is not validly derived from the "
10756 "item type %s of the base type %s",
10757 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
10758 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
10759 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10760
10761 FREE_AND_NULL(str)
10762 FREE_AND_NULL(strBIT)
10763 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010764 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
10765 }
10766 }
10767
10768 if (type->facets != NULL) {
10769 xmlSchemaFacetPtr facet;
10770 int ok = 1;
10771 /*
10772 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
10773 * and enumeration facet components are allowed among the {facets}.
10774 */
10775 facet = type->facets;
10776 do {
10777 switch (facet->type) {
10778 case XML_SCHEMA_FACET_LENGTH:
10779 case XML_SCHEMA_FACET_MINLENGTH:
10780 case XML_SCHEMA_FACET_MAXLENGTH:
10781 case XML_SCHEMA_FACET_WHITESPACE:
10782 /*
10783 * TODO: 2.5.1.2 List datatypes
10784 * The value of ·whiteSpace· is fixed to the value collapse.
10785 */
10786 case XML_SCHEMA_FACET_PATTERN:
10787 case XML_SCHEMA_FACET_ENUMERATION:
10788 break;
10789 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010790 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010791 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010792 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010793 /*
10794 * We could return, but it's nicer to report all
10795 * invalid facets.
10796 */
10797 ok = 0;
10798 }
10799 }
10800 facet = facet->next;
10801 } while (facet != NULL);
10802 if (ok == 0)
10803 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
10804 /*
10805 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
10806 * is a facet of the same kind in the {facets} of the {base type
10807 * definition} (call this BF),then the DF's {value} must be a valid
10808 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
10809 */
10810 }
10811
10812
10813 }
10814 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10815 /*
10816 * 3.1 The {member type definitions} must all have {variety} of
10817 * atomic or list.
10818 */
10819 xmlSchemaTypeLinkPtr member;
10820
10821 member = type->memberTypes;
10822 while (member != NULL) {
10823 if (((member->type->flags &
10824 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10825 ((member->type->flags &
10826 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010827 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010828 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010829 NULL, type, NULL,
10830 "The member type %s is neither an atomic, nor a list type",
10831 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10832 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010833 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
10834 }
10835 member = member->next;
10836 }
10837 /*
10838 * 3.3.1 If the {base type definition} is the ·simple ur-type
10839 * definition·
10840 */
10841 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10842 /*
10843 * 3.3.1.1 All of the {member type definitions} must have a
10844 * {final} which does not contain union.
10845 */
10846 member = type->memberTypes;
10847 while (member != NULL) {
10848 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
10849 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010850 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010851 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010852 NULL, type, NULL,
10853 "The final of member type %s contains 'union'",
10854 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10855 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010856 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
10857 }
10858 member = member->next;
10859 }
10860 /*
10861 * 3.3.1.2 The {facets} must be empty.
10862 */
10863 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010864 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010865 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010866 NULL, type, NULL,
10867 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010868 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
10869 }
10870 } else {
10871 /*
10872 * 3.3.2.1 The {base type definition} must have a {variety} of union.
10873 */
10874 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010875 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010876 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010877 NULL, type, NULL,
10878 "The base type %s is not a union type",
10879 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10880 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010881 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
10882 }
10883 /*
10884 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
10885 */
10886 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10887 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010888 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010889 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010890 NULL, type, NULL,
10891 "The final of its base type %s must not contain 'restriction'",
10892 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10893 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010894 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
10895 }
10896 /*
10897 * 3.3.2.3 The {member type definitions}, in order, must be validly
10898 * derived from the corresponding type definitions in the {base
10899 * type definition}'s {member type definitions} given the empty set,
10900 * as defined in Type Derivation OK (Simple) (§3.14.6).
10901 */
10902 {
10903 xmlSchemaTypeLinkPtr baseMember;
10904
10905 /*
10906 * OPTIMIZE: if the type is restricting, it has no local defined
10907 * member types and inherits the member types of the base type;
10908 * thus a check for equality can be skipped.
10909 */
10910 /*
10911 * TODO: Even worse: I cannot see a scenario where a restricting
10912 * union simple type can have other member types as the member
10913 * types of it's base type. This check seems not necessary with
10914 * respect to the derivation process in libxml2.
10915 */
10916 if (type->memberTypes != NULL) {
10917 member = type->memberTypes;
10918 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
10919 if ((member == NULL) && (baseMember != NULL)) {
10920 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010921 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010922 "Internal error: "
10923 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010924 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000010925 "of member types in the base type\n",
10926 type->name, NULL);
10927 }
10928 while (member != NULL) {
10929 if (baseMember == NULL) {
10930 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010931 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010932 "Internal error: "
10933 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010934 "(3.3.2.3), union simple type '%s', unequal number "
10935 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010936 type->name, NULL);
10937 }
10938 if ((member->type != baseMember->type) &&
10939 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
10940 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010941 xmlChar *strBMT = NULL, *strBT = NULL;
10942
10943 xmlSchemaPCustomErrExt(ctxt,
10944 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
10945 NULL, type, NULL,
10946 "The member type %s is not validly derived from its "
10947 "corresponding member type %s of the base type %s",
10948 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
10949 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
10950 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
10951 FREE_AND_NULL(str)
10952 FREE_AND_NULL(strBMT)
10953 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010954 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
10955 }
10956 member = member->next;
10957 baseMember = baseMember->next;
10958 }
10959 }
10960 }
10961 /*
10962 * 3.3.2.4 Only pattern and enumeration facet components are
10963 * allowed among the {facets}.
10964 */
10965 if (type->facets != NULL) {
10966 xmlSchemaFacetPtr facet;
10967 int ok = 1;
10968
10969 facet = type->facets;
10970 do {
10971 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
10972 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010973 xmlSchemaPIllegalFacetListUnionErr(ctxt,
10974 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
10975 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010976 ok = 0;
10977 }
10978 facet = facet->next;
10979 } while (facet != NULL);
10980 if (ok == 0)
10981 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
10982
10983 }
10984 /*
10985 * TODO: 3.3.2.5 (facet derivation)
10986 */
10987 }
10988 }
10989
10990 return (0);
10991}
10992
10993/**
10994 * xmlSchemaCheckSRCSimpleType:
10995 * @ctxt: the schema parser context
10996 * @type: the simple type definition
10997 *
10998 * Checks crc-simple-type constraints.
10999 *
11000 * Returns 0 if the constraints are satisfied,
11001 * if not a positive error code and -1 on internal
11002 * errors.
11003 */
11004static int
11005xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11006 xmlSchemaTypePtr type)
11007{
11008 /*
11009 * NOTE: src-simple-type 2-4 are redundant, since the checks
11010 * were are done for the corresponding <restriction>, <list> and <union>
11011 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11012 * Maby this can be skipped in the future, if we get sure it's not needed.
11013 */
11014 if (type->subtypes == NULL) {
11015 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011016 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011017 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011018 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011019 type->name, NULL);
11020 return (-1);
11021 }
11022 /*
11023 * src-simple-type.1 The corresponding simple type definition, if any,
11024 * must satisfy the conditions set out in Constraints on Simple Type
11025 * Definition Schema Components (§3.14.6).
11026 */
11027 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11028 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11029 /*
11030 * TODO: Removed this, since it got annoying to get an
11031 * extra error report, if anything failed until now.
11032 * Enable this if needed.
11033 */
11034 /*
11035 xmlSchemaPErr(ctxt, type->node,
11036 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011037 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011038 "on simple type definitions.\n",
11039 type->name, NULL);
11040 */
11041 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11042 }
11043
11044 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11045 /*
11046 * src-simple-type.2 If the <restriction> alternative is chosen,
11047 * either it must have a base [attribute] or a <simpleType> among its
11048 * [children], but not both.
11049 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011050 /*
11051 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11052 * NOTE: This was removed, since this will be already handled
11053 * in the parse function for <restriction>.
11054 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011055 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11056 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11057 * an itemType [attribute] or a <simpleType> among its [children],
11058 * but not both.
11059 * NOTE: baseType is set to the local simple type definiton,
11060 * if existent, at parse time. This is a hack and not nice.
11061 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011062 /*
11063 * TODO: Remove this, and add the check to the parse function of <list>.
11064 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011065 if (((type->subtypes->base == NULL) &&
11066 (type->baseType == NULL)) ||
11067 ((type->subtypes->base != NULL) &&
11068 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011069 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011070 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 NULL, type, NULL,
11072 "Either the attribute 'itemType' or the <simpleType> child "
11073 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011074 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11075 }
11076
11077
11078 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11079 xmlSchemaTypeLinkPtr member;
11080 xmlSchemaTypePtr ancestor, anySimpleType;
11081
11082 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11083
11084 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11085 * the <union> alternative is chosen, there must not be any entries
11086 * in the memberTypes [attribute] at any depth which resolve to the
11087 * component corresponding to the <simpleType>.
11088 */
11089 member = type->memberTypes;
11090 while (member != NULL) {
11091 ancestor = member->type;
11092 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11093 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11094 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11095 if (ancestor == anySimpleType)
11096 break;
11097 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011099 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011100 NULL, type, NULL,
11101 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011102 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11103 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11104 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011106 * type as item type, which in turn has a list ST as member
11107 * type, we will assume this here as well, since this check
11108 * was not yet performed.
11109 */
11110
11111 }
11112 ancestor = ancestor->baseType;
11113 }
11114 member = member->next;
11115 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011116 }
11117
11118 return (0);
11119}
11120
William M. Brack2f2a6632004-08-20 23:09:47 +000011121#if 0 /* Not yet used code for CT schema validation */
11122static int
11123xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11124 const xmlChar * value,
11125 xmlSchemaTypePtr type,
11126 int fireErrors)
11127{
11128 int ret;
11129 /*
11130 * 3.14.4 Simple Type Definition Validation Rules
11131 * Validation Rule: String Valid
11132 */
11133 /*
11134 * 1 It is schema-valid with respect to that definition as defined
11135 * by Datatype Valid in [XML Schemas: Datatypes].
11136 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011137 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11138 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011139 return (ret);
11140 /*
11141 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11142 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11143 * the string must be a ·declared entity name·.
11144 */
11145 /*
11146 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11147 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11148 * then every whitespace-delimited substring of the string must be a ·declared
11149 * entity name·.
11150 */
11151 /*
11152 * 2.3 otherwise no further condition applies.
11153 */
11154
11155 return (0);
11156}
11157
11158
11159static int
11160xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr ctxt,
11161 xmlSchemaElementPtr elemDecl)
11162{
11163 xmlSchemaTypePtr typeDef;
11164 if (elemDecl->value == NULL)
11165 return (0);
11166 if (elemDecl->subtypes == NULL) {
11167 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011168 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011169 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
11170 "Internal error: xmlSchemaCheckCOSValidDefault, "
11171 "the element decl. '%s' has no type assigned", elemDecl->name);
11172 return (-1);
11173 }
11174 typeDef = elemDecl->subtypes;
11175 if ((typeDef->type == XML_SCHEMA_TYPE_SIMPLE) ||
11176 ((typeDef->type == XML_SCHEMA_TYPE_COMPLEX) &&
11177 ((typeDef->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
11178 (typeDef->contentType == XML_SCHEMA_CONTENT_BASIC)))) {
11179 xmlSchemaValidCtxtPtr vctxt;
11180 xmlAttrPtr attr;
11181 int ret = 0;
11182 /*
11183 * 1 If the type definition is a simple type definition, then the string
11184 * must be ·valid· with respect to that definition as defined by String
11185 * Valid (§3.14.4).
11186 */
11187 /*
11188 * 2.2.1 If the {content type} is a simple type definition, then the
11189 * string must be ·valid· with respect to that simple type definition
11190 * as defined by String Valid (§3.14.4).
11191 */
11192 /*
11193 * TODO: ?
11194 */
11195
11196 vctxt = xmlSchemaNewValidCtxt(NULL);
11197 if (vctxt == NULL) {
11198 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011199 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011200 "Internal error: xmlSchemaCheckCOSValidDefault, "
11201 "creation of a new validation context failed.\n",
11202 NULL, NULL);
11203 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011204 }
11205 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
11206 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
11207 else
11208 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
William M. Brack2f2a6632004-08-20 23:09:47 +000011209 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011210 * TODO: This won't work yet.
William M. Brack2f2a6632004-08-20 23:09:47 +000011211 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011212 if (typeDef->type == XML_SCHEMA_TYPE_SIMPLE) {
11213 vctxt->node = elemDecl->node;
11214 vctxt->cur = attr->children;
11215 ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0);
11216 }
11217 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011218 if (ctxt != NULL) {
11219 xmlSchemaPSimpleTypeErr(ctxt,
11220 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11221 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
11222 elemDecl->subtypes, NULL, elemDecl->value,
11223 NULL, NULL, NULL);
11224 return (ctxt->err);
11225 }
11226 ret = ctxt->err;
11227 } else if (ret < 0) {
11228 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011229 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011230 "Internal error: xmlSchemaCheckCOSValidDefault, "
11231 "while validating the default/fixed value.\n",
11232 NULL, NULL);
11233 }
11234 xmlSchemaFreeValidCtxt(vctxt);
11235 return (ret);
11236 } else {
11237 /*
11238 * Complex type.
11239 *
11240 * 2.1 its {content type} must be a simple type definition or mixed.
11241 */
11242 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11243 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11244 (elemDecl->subtypes->contentType == XML_SCHEMA_CONTENT_MIXED)) {
11245 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11246 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
11247 "The content type must be a simple type definition or mixed.",
11248 NULL);
11249 return(ctxt->err);
11250 }
11251 if ((elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11252 (elemDecl->subtypes->contentType != XML_SCHEMA_CONTENT_BASIC)) {
11253 xmlSchemaValidCtxtPtr vctxt;
11254 xmlAttrPtr attr;
11255 int ret;
11256
11257 /* TODO: Avoid creation of a new context. */
11258 vctxt = xmlSchemaNewValidCtxt(NULL);
11259 if (vctxt == NULL) {
11260 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011261 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011262 "Internal error: xmlSchemaCheckCOSValidDefault, "
11263 "creation of a new validation context failed.\n",
11264 NULL, NULL);
11265 return (-1);
11266 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011267
11268 ret = xmlSchemaValidateSimpleTypeValue(vctxt, elemDecl->subtypes,
11269 elemDecl->value, 0, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011270 if (ret > 0) {
11271 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
11272 attr = xmlSchemaGetPropNode(elemDecl->node, "fixed");
11273 else
11274 attr = xmlSchemaGetPropNode(elemDecl->node, "default");
11275 if (ctxt != NULL) {
11276 xmlSchemaPSimpleTypeErr(ctxt,
11277 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11278 NULL, (xmlSchemaTypePtr) elemDecl, (xmlNodePtr) attr,
11279 elemDecl->subtypes, NULL, elemDecl->value,
11280 NULL, NULL, NULL);
11281 return (ctxt->err);
11282 }
11283 ret = ctxt->err;
11284 } else if (ret < 0) {
11285 xmlSchemaPErr(ctxt, elemDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011286 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011287 "Internal error: xmlSchemaCheckCOSValidDefault, "
11288 "while validating the default/fixed value.\n",
11289 NULL, NULL);
11290 }
11291 xmlSchemaFreeValidCtxt(vctxt);
11292 return (ret);
11293 } else {
11294 /*
11295 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11296 * particle must be ·emptiable· as defined by Particle Emptiable
11297 * (§3.9.6).
11298 */
11299 /*
11300 * TODO: Implement this.
11301 */
11302 }
11303 }
11304
11305 return (0);
11306}
11307
11308/**
11309 * xmlSchemaGetSTContentOfCT:
11310 * @ctxt: the schema parser context
11311 * @type: the complex type definition
11312 *
11313 *
11314 * Returns the corresponding simple type for the content of
11315 * the complex type.
11316 */
11317static xmlSchemaTypePtr
11318xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11319 xmlSchemaTypePtr type)
11320{
11321 xmlSchemaTypePtr orig = type, anyType;
11322
11323 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11324 while ((type != NULL) && (type != anyType) &&
11325 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11326 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11327 return(type);
11328 type = type->baseType;
11329 }
11330 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011331 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011332 NULL, orig, NULL,
11333 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11334 "no simple type for the content of complex type '%s' could be "
11335 "computed", orig->name);
11336 return (NULL);
11337}
11338
11339
11340static xmlSchemaTypePtr
11341xmlSchemaGetContentType(xmlSchemaParserCtxtPtr ctxt,
11342 xmlSchemaTypePtr type)
11343{
11344 if (type->baseType == NULL) {
11345 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011346 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011347 NULL, type, NULL,
11348 "Internal error: xmlSchemaGetContentType, "
11349 "the complex type '%s' has no base type", type->name);
11350 return (NULL);
11351 }
11352 if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11353 if ((type->baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11354 ((type->baseType->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
11355 (type->baseType->contentType == XML_SCHEMA_CONTENT_BASIC)) &&
11356 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
11357 /*
11358 * 1 If the type definition ·resolved· to by the ·actual value· of
11359 * the base [attribute] is a complex type definition whose own
11360 * {content type} is a simple type definition and the <restriction>
11361 * alternative is chosen
11362 */
11363
11364
11365 }
11366 } else {
11367
11368 }
11369}
11370
11371/**
11372 * xmlSchemaCheckCOSCTExtends:
11373 * @ctxt: the schema parser context
11374 * @type: the complex type definition
11375 *
11376 * Schema Component Constraint: Derivation Valid (Extension)
11377 *
11378 * Returns 0 if the constraints are satisfied, a positive
11379 * error code if not and -1 if an internal error occured.
11380 */
11381static int
11382xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11383 xmlSchemaTypePtr type)
11384{
11385 xmlSchemaTypePtr base;
11386 /*
11387 * 1 If the {base type definition} is a complex type definition,
11388 * then all of the following must be true:
11389 */
11390 base = type->baseType;
11391 if (base == NULL) {
11392 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011393 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011394 NULL, type, NULL,
11395 "Internal error: xmlSchemaCheckCOSCTExtends, "
11396 "the complex type '%s' has no base type", type->name);
11397 return (-1);
11398 }
11399 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11400 /*
11401 * 1.1 The {final} of the {base type definition} must not
11402 * contain extension.
11403 */
11404 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11405 xmlSchemaPCustomErr(ctxt,
11406 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11407 NULL, type, NULL,
11408 "The 'final' of the base type definition "
11409 "contains extension", NULL);
11410 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11411 }
11412 /*
11413 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11414 * of the complex type definition itself, that is, for every attribute
11415 * use in the {attribute uses} of the {base type definition}, there
11416 * must be an attribute use in the {attribute uses} of the complex
11417 * type definition itself whose {attribute declaration} has the same
11418 * {name}, {target namespace} and {type definition} as its attribute
11419 * declaration
11420 *
11421 * NOTE: This will be already satisfied by the way the attribute uses
11422 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11423 * is not needed.
11424 */
11425
11426 /*
11427 * 1.3 If it has an {attribute wildcard}, the complex type definition
11428 * must also have one, and the base type definition's {attribute
11429 * wildcard}'s {namespace constraint} must be a subset of the complex
11430 * type definition's {attribute wildcard}'s {namespace constraint},
11431 * as defined by Wildcard Subset (§3.10.6).
11432 *
11433 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11434 * this check is not needed.
11435 */
11436
11437 /*
11438 * 1.4 One of the following must be true:
11439 *
11440 * 1.4.1 The {content type} of the {base type definition} and the
11441 * {content type} of the complex type definition itself must be the same
11442 * simple type definition
11443 */
11444
11445
11446
11447 } else {
11448 /*
11449 * 2 If the {base type definition} is a simple type definition,
11450 * then all of the following must be true:
11451 */
11452 /*
11453 * 2.1 The {content type} must be the same simple type definition.
11454 */
11455 /*
11456 * 2.2 The {final} of the {base type definition} must not contain
11457 * extension
11458 */
11459 }
11460
11461}
11462
11463#endif
11464
Daniel Veillard01fa6152004-06-29 17:04:39 +000011465/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011466 * xmlSchemaGroupDefFixup:
11467 * @typeDecl: the schema model group definition
11468 * @ctxt: the schema parser context
11469 *
11470 * Fixes model group definitions.
11471 */
11472static void
11473xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11474 xmlSchemaParserCtxtPtr ctxt,
11475 const xmlChar * name ATTRIBUTE_UNUSED)
11476{
11477 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11478 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11479 xmlSchemaTypePtr groupDef;
11480 /*
11481 * Resolve the reference.
11482 */
11483 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11484 group->refNs);
11485 if (groupDef == NULL) {
11486 xmlSchemaPResCompAttrErr(ctxt,
11487 XML_SCHEMAP_SRC_RESOLVE,
11488 NULL, group, NULL,
11489 "ref", group->ref, group->refNs,
11490 XML_SCHEMA_TYPE_GROUP, NULL);
11491 return;
11492 }
11493 group->subtypes = groupDef;
11494 }
11495}
11496
11497/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011498 * xmlSchemaTypeFixup:
11499 * @typeDecl: the schema type definition
11500 * @ctxt: the schema parser context
11501 *
11502 * Fixes the content model of the type.
11503 */
11504static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011505xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011506 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000011507{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011508 xmlSchemaTypePtr ctxtType;
11509
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011510 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000011511 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011512 /*
11513 * Do not allow the following types to be typefixed, prior to
11514 * the corresponding simple/complex types.
11515 */
11516 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011517 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011518 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
11519 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
11520 case XML_SCHEMA_TYPE_UNION:
11521 case XML_SCHEMA_TYPE_RESTRICTION:
11522 case XML_SCHEMA_TYPE_EXTENSION:
11523 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011524 default:
11525 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011526 }
11527 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011528 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011529 name = item->name;
11530 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
11531 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011532 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011533 if (item->subtypes != NULL) {
11534 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011535 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011536 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011537 NULL);
11538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011539 item->contentType =
11540 item->subtypes->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011541 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011542 break;
11543 }
11544 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011545 xmlSchemaTypePtr base = NULL;
11546
11547 ctxt->ctxtType->flags |=
11548 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011549 if (item->baseType != NULL)
11550 base = item->baseType;
11551 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011552 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011553 xmlSchemaGetType(ctxt->schema, item->base,
11554 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011555 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011556 xmlSchemaPResCompAttrErr(ctxt,
11557 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000011558 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011559 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
11560 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011561 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011562 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000011563 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011564 xmlSchemaTypeFixup(base, ctxt, NULL);
11565 }
William M. Brack2f2a6632004-08-20 23:09:47 +000011566 }
11567 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011568 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
11569 /*
11570 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000011571 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011572 /*
11573 * Content type.
11574 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011575 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011576 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011577 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
11578 else if ((item->subtypes->subtypes == NULL) &&
11579 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011580 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011581 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011582 XML_SCHEMA_TYPE_SEQUENCE)))
11583 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011584 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
11585 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011586 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011587 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011588 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011589 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011590 else {
11591 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011592 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011593 XML_SCHEMA_CONTENT_ELEMENTS;
11594 }
11595 } else {
11596 /*
11597 * SimpleType restriction.
11598 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011599 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011601 break;
11602 }
11603 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000011604 xmlSchemaTypePtr base = NULL;
11605 xmlSchemaContentType explicitContentType;
11606
11607 /*
11608 * An extension does exist on a complexType only.
11609 */
11610 ctxt->ctxtType->flags |=
11611 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011612 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011613 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011614 xmlSchemaPCustomErr(ctxt,
11615 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011616 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011617 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000011618 return;
11619 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011620 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011621 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011622 xmlSchemaGetType(ctxt->schema, item->base,
11623 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011624 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011625 xmlSchemaPResCompAttrErr(ctxt,
11626 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011627 NULL, item, item->node,
11628 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011629 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000011630 } else if (base->contentType ==
11631 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011632 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011633 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011634 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011635 }
11636 /*
11637 * The type definition ·resolved· to by the ·actual
11638 * value· of the base [attribute]
11639 */
11640 ctxt->ctxtType->baseType = base;
11641 /*
11642 * TODO: This one is still needed for computation of
11643 * the content model by xmlSchemaBuildAContentModel.
11644 * Try to get rid of it.
11645 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011646 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011647 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011648 if ((item->subtypes != NULL) &&
11649 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
11650 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011651
11652 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011653 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011654 /* 1.1.1 */
11655 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011656 else if ((item->subtypes->subtypes == NULL) &&
11657 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011658 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011659 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011660 XML_SCHEMA_TYPE_SEQUENCE)))
11661 /* 1.1.2 */
11662 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011663 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011664 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011665 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011666 /* 1.1.3 */
11667 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
11668 if (base != NULL) {
11669 /* It will be reported later, if the base is missing. */
11670 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
11671 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011672 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011673 } else if (base->contentType ==
11674 XML_SCHEMA_CONTENT_EMPTY) {
11675 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011676 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011677 XML_SCHEMA_CONTENT_ELEMENTS;
11678 } else {
11679 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011680 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011681 XML_SCHEMA_CONTENT_ELEMENTS;
11682 }
11683 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011684 break;
11685 }
11686 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011687 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011688 ctxt->ctxtType = item;
11689 /*
11690 * Start with an empty content-type type.
11691 */
11692 if (item->subtypes == NULL)
11693 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
11694
11695 if ((item->subtypes == NULL) ||
11696 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000011697 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011698 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
11700 /*
11701 * This case is understood as shorthand for complex
11702 * content restricting the ur-type definition, and
11703 * the details of the mappings should be modified as
11704 * necessary.
11705 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011706 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11707 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000011708 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011709 /*
11710 * Assume that we inherit the content-type type from 'anyType'.
11711 */
11712 item->contentType = item->baseType->contentType;
11713 }
11714 /*
11715 * Fixup the sub components.
11716 */
11717 if ((item->subtypes != NULL) &&
11718 (item->subtypes->contentType ==
11719 XML_SCHEMA_CONTENT_UNKNOWN)) {
11720 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011721 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011722 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
11723 item->contentType = XML_SCHEMA_CONTENT_MIXED;
11724 } else if (item->subtypes != NULL) {
11725 /*
11726 * Use the content-type type of the model groups
11727 * defined, if 'mixed' is not set. If 'mixed' is set
11728 * it will expand the content-type by allowing character
11729 * content to appear.
11730 */
11731 item->contentType =
11732 item->subtypes->contentType;
11733 }
11734 xmlSchemaBuildAttributeValidation(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011735 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011736 break;
11737 }
11738 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011739 if (item->subtypes == NULL) {
11740 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
11741 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
11742 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000011743 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011744 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011745 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
11746 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011747 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000011748 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011749 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011750 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011751 if (item->subtypes != NULL)
11752 item->contentType =
11753 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011754 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011755 /*
11756 * Removed due to implementation of the build of attribute uses.
11757 */
11758 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011759 if (item->attributes == NULL)
11760 item->attributes =
11761 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000011762 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011763 }
11764 break;
11765 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011766 case XML_SCHEMA_TYPE_SIMPLE:
11767 /*
11768 * Simple Type Definition Schema Component
11769 *
11770 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011771 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011772 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11773 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011774 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011775 ctxt->ctxtType = item;
11776 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011777 }
11778 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011779 if ((item->baseType != NULL) &&
11780 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011781 XML_SCHEMA_CONTENT_UNKNOWN)) {
11782 /* OPTIMIZE: Actually this one will never by hit, since
11783 * the base type is already type-fixed in <restriction>.
11784 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011785 ctxt->ctxtType = item;
11786 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011787 }
11788 /* Base type:
11789 * 2 If the <list> or <union> alternative is chosen,
11790 * then the ·simple ur-type definition·.
11791 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011792 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011793 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011794 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11795 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11796 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011797 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011798 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11799 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
11800 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000011801 XML_SCHEMA_TYPE_RESTRICTION) {
11802 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
11803
11804 /*
11805 * Variety
11806 * If the <restriction> alternative is chosen, then the
11807 * {variety} of the {base type definition}.
11808 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011809 if (item->baseType != NULL) {
11810 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000011811 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011812 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
11813 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000011814 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011815 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
11816 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000011817 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011818 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011819 /*
11820 * Schema Component Constraint: Simple Type Restriction
11821 * (Facets)
11822 * NOTE: Satisfaction of 1 and 2 arise from the fixup
11823 * applied beforehand.
11824 *
11825 * 3 The {facets} of R are the union of S and the {facets}
11826 * of B, eliminating duplicates. To eliminate duplicates,
11827 * when a facet of the same kind occurs in both S and the
11828 * {facets} of B, the one in the {facets} of B is not
11829 * included, with the exception of enumeration and pattern
11830 * facets, for which multiple occurrences with distinct values
11831 * are allowed.
11832 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011833 if (item->baseType->facetSet != NULL) {
11834 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011835 if (last != NULL)
11836 while (last->next != NULL)
11837 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011838 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011839 for (; cur != NULL; cur = cur->next) {
11840 /*
11841 * Base patterns won't be add here:
11842 * they are ORed in a type and
11843 * ANDed in derived types. This will
11844 * happed at validation level by
11845 * walking the base axis of the type.
11846 */
11847 if (cur->facet->type ==
11848 XML_SCHEMA_FACET_PATTERN)
11849 continue;
11850 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011851 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011852 (cur->facet->type !=
11853 XML_SCHEMA_FACET_PATTERN) &&
11854 (cur->facet->type !=
11855 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011856 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011857 do {
11858 if (cur->facet->type ==
11859 facet->facet->type)
11860 break;
11861 facet = facet->next;
11862 } while (facet != NULL);
11863 }
11864 if (facet == NULL) {
11865 facet = (xmlSchemaFacetLinkPtr)
11866 xmlMalloc(sizeof(xmlSchemaFacetLink));
11867 if (facet == NULL) {
11868 xmlSchemaPErrMemory(ctxt,
11869 "fixing simpleType", NULL);
11870 return;
11871 }
11872 facet->facet = cur->facet;
11873 facet->next = NULL;
11874 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011875 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011876 else
11877 last->next = facet;
11878 last = facet;
11879 }
11880 }
11881 }
11882 }
11883 }
11884 /*
11885 * Check constraints.
11886 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011887 xmlSchemaCheckSRCSimpleType(ctxt, item);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000011888 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011889 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011890 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011891 case XML_SCHEMA_TYPE_ALL:
11892 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011893 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011894 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011895 case XML_SCHEMA_TYPE_GROUP:
11896 /*
11897 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
11898 */
11899 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011900 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011901 xmlSchemaParseListRefFixup(item, ctxt);
11902 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011903 break;
11904 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011905 xmlSchemaParseUnionRefCheck(item, ctxt);
11906 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011907 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011908 case XML_SCHEMA_TYPE_BASIC:
11909 case XML_SCHEMA_TYPE_ANY:
11910 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011911 case XML_SCHEMA_TYPE_UR:
11912 case XML_SCHEMA_TYPE_ELEMENT:
11913 case XML_SCHEMA_TYPE_ATTRIBUTE:
11914 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000011915 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011916 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011917 case XML_SCHEMA_FACET_MININCLUSIVE:
11918 case XML_SCHEMA_FACET_MINEXCLUSIVE:
11919 case XML_SCHEMA_FACET_MAXINCLUSIVE:
11920 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
11921 case XML_SCHEMA_FACET_TOTALDIGITS:
11922 case XML_SCHEMA_FACET_FRACTIONDIGITS:
11923 case XML_SCHEMA_FACET_PATTERN:
11924 case XML_SCHEMA_FACET_ENUMERATION:
11925 case XML_SCHEMA_FACET_WHITESPACE:
11926 case XML_SCHEMA_FACET_LENGTH:
11927 case XML_SCHEMA_FACET_MAXLENGTH:
11928 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011929 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11930 if (item->subtypes != NULL)
11931 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011932 break;
11933 }
11934 }
Daniel Veillard8651f532002-04-17 09:06:27 +000011935#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011936 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011937 xmlGenericError(xmlGenericErrorContext,
11938 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011939 item->node->doc->URL,
11940 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011941 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011942 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011943 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011944 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011945 case XML_SCHEMA_CONTENT_SIMPLE:
11946 xmlGenericError(xmlGenericErrorContext, "simple\n");
11947 break;
11948 case XML_SCHEMA_CONTENT_ELEMENTS:
11949 xmlGenericError(xmlGenericErrorContext, "elements\n");
11950 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011951 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011952 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
11953 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011954 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011955 xmlGenericError(xmlGenericErrorContext, "empty\n");
11956 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011957 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011958 xmlGenericError(xmlGenericErrorContext, "mixed\n");
11959 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011960 /* Removed, since not used. */
11961 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000011962 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011963 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
11964 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011965 */
Daniel Veillard8651f532002-04-17 09:06:27 +000011966 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011967 xmlGenericError(xmlGenericErrorContext, "basic\n");
11968 break;
11969 default:
11970 xmlGenericError(xmlGenericErrorContext,
11971 "not registered !!!\n");
11972 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000011973 }
11974#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011975}
11976
11977/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011978 * xmlSchemaCheckFacet:
11979 * @facet: the facet
11980 * @typeDecl: the schema type definition
11981 * @ctxt: the schema parser context or NULL
11982 * @name: name of the type
11983 *
11984 * Checks the default values types, especially for facets
11985 *
11986 * Returns 0 if okay or -1 in cae of error
11987 */
11988int
11989xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011990 xmlSchemaTypePtr typeDecl,
11991 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011992{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000011993 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011994 int ret = 0;
11995
11996 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011997 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000011998 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000011999 }
12000 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012001 case XML_SCHEMA_FACET_MININCLUSIVE:
12002 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12003 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012004 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12005 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012006 /*
12007 * Okay we need to validate the value
12008 * at that point.
12009 */
12010 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012011 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012012
12013 /* 4.3.5.5 Constraints on enumeration Schema Components
12014 * Schema Component Constraint: enumeration valid restriction
12015 * It is an ·error· if any member of {value} is not in the
12016 * ·value space· of {base type definition}.
12017 *
12018 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12019 * The value ·must· be in the
12020 * ·value space· of the ·base type·.
12021 */
12022 /*
12023 * This function is intended to deliver a compiled value
12024 * on the facet. In XML Schemas the type holding a facet,
12025 * cannot be a built-in type. Thus to ensure that other API
12026 * calls (relaxng) do work, if the given type is a built-in
12027 * type, we will assume that the given built-in type *is
12028 * already* the base type.
12029 */
12030 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12031 base = typeDecl->baseType;
12032 if (base == NULL) {
12033 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012034 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012035 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012036 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012037 typeDecl->name, NULL);
12038 return (-1);
12039 }
12040 } else
12041 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012042 /*
12043 * TODO: Try to avoid creating a new context.
12044 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012045 vctxt = xmlSchemaNewValidCtxt(NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012046 if (vctxt == NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012047 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012048 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012049 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012050 "creating a new validation context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012051 NULL, NULL);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012052 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012053 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012054 vctxt->node = facet->node;
12055 vctxt->cur = NULL;
12056 /*
12057 * NOTE: This call does not check the content nodes,
12058 * since they are not available:
12059 * facet->node is just the node holding the facet
12060 * definition, *not* the attribute holding the *value*
12061 * of the facet.
12062 */
12063 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12064 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012065 facet->val = vctxt->value;
12066 vctxt->value = NULL;
12067 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012068 /* error code */
12069 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012070 xmlSchemaPErrExt(ctxt, facet->node,
12071 XML_SCHEMAP_INVALID_FACET,
12072 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012073 "Type definition '%s': The value '%s' of the "
12074 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012075 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012076 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012077 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012078 }
12079 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012080 } else if (ret < 0) {
12081 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012082 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012083 NULL, NULL, NULL,
12084 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012085 "failed to validate the value '%s' name of the "
12086 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012087 facet->value,
12088 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12089 base->name, NULL, NULL);
12090 ret = -1;
12091 }
12092 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012093 break;
12094 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012095 case XML_SCHEMA_FACET_PATTERN:
12096 facet->regexp = xmlRegexpCompile(facet->value);
12097 if (facet->regexp == NULL) {
12098 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012099 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012100 "Type definition '%s': The value '%s' of the "
12101 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012102 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012103 ret = -1;
12104 }
12105 break;
12106 case XML_SCHEMA_FACET_TOTALDIGITS:
12107 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12108 case XML_SCHEMA_FACET_LENGTH:
12109 case XML_SCHEMA_FACET_MAXLENGTH:
12110 case XML_SCHEMA_FACET_MINLENGTH:{
12111 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012112
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012113 tmp =
12114 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12115 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012116 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012117 if (tmp != 0) {
12118 /* error code */
12119 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012120 xmlSchemaPErrExt(ctxt, facet->node,
12121 XML_SCHEMAP_INVALID_FACET_VALUE,
12122 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012123 "Type definition '%s': The value '%s' of the "
12124 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012125 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012126 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012127 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012128 }
12129 ret = -1;
12130 }
12131 break;
12132 }
12133 case XML_SCHEMA_FACET_WHITESPACE:{
12134 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12135 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12136 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12137 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12138 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12139 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12140 } else {
12141 if (ctxt != NULL) {
12142 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012144 "Type definition '%s': The value '%s' of the "
12145 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012146 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012147 }
12148 ret = -1;
12149 }
12150 }
12151 default:
12152 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012153 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012154 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012155}
12156
12157/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012158 * xmlSchemaCheckDefaults:
12159 * @typeDecl: the schema type definition
12160 * @ctxt: the schema parser context
12161 *
12162 * Checks the default values types, especially for facets
12163 */
12164static void
12165xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012166 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012167{
Daniel Veillard4255d502002-04-16 15:50:10 +000012168 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 name = typeDecl->name;
12170 /*
12171 * NOTE: It is intended to use the facets list, instead
12172 * of facetSet.
12173 */
12174 if (typeDecl->facets != NULL) {
12175 xmlSchemaFacetPtr facet = typeDecl->facets;
12176
12177 while (facet != NULL) {
12178 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12179 facet = facet->next;
12180 }
12181 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012182}
12183
12184/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012185 * xmlSchemaGetCircModelGrDefRef:
12186 * @ctxtGr: the searched model group
12187 * @list: the list of model groups to be processed
12188 *
12189 * This one is intended to be used by
12190 * xmlSchemaCheckGroupDefCircular only.
12191 *
12192 * Returns the circular model group definition reference, otherwise NULL.
12193 */
12194static xmlSchemaTypePtr
12195xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12196 xmlSchemaTypePtr gr)
12197{
12198 xmlSchemaTypePtr circ = NULL;
12199 int marked;
12200 /*
12201 * We will search for an model group reference which
12202 * references the context model group definition.
12203 */
12204 while (gr != NULL) {
12205 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12206 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12207 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12208 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12209 (gr->subtypes != NULL)) {
12210 marked = 0;
12211 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12212 (gr->ref != NULL)) {
12213 if (gr->subtypes == ctxtGrDef)
12214 return (gr);
12215 else if (gr->subtypes->flags &
12216 XML_SCHEMAS_TYPE_MARKED) {
12217 gr = gr->next;
12218 continue;
12219 } else {
12220 /*
12221 * Mark to avoid infinite recursion on
12222 * circular references not yet examined.
12223 */
12224 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12225 marked = 1;
12226 }
12227 if (gr->subtypes->subtypes != NULL)
12228 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12229 gr->subtypes->subtypes);
12230 /*
12231 * Unmark the visited model group definition.
12232 */
12233 if (marked)
12234 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12235 if (circ != NULL)
12236 return (circ);
12237 } else {
12238 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12239 (xmlSchemaTypePtr) gr->subtypes);
12240 if (circ != NULL)
12241 return (circ);
12242 }
12243
12244 }
12245 gr = gr->next;
12246 }
12247 return (NULL);
12248}
12249
12250/**
12251 * xmlSchemaCheckGroupDefCircular:
12252 * attrGr: the model group definition
12253 * @ctxt: the parser context
12254 * @name: the name
12255 *
12256 * Checks for circular references to model group definitions.
12257 */
12258static void
12259xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12260 xmlSchemaParserCtxtPtr ctxt,
12261 const xmlChar * name ATTRIBUTE_UNUSED)
12262{
12263 /*
12264 * Schema Component Constraint: Model Group Correct
12265 * 2 Circular groups are disallowed. That is, within the {particles}
12266 * of a group there must not be at any depth a particle whose {term}
12267 * is the group itself.
12268 */
12269 /*
12270 * NOTE: "gr->subtypes" holds the referenced group.
12271 */
12272 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12273 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12274 (modelGrDef->subtypes == NULL))
12275 return;
12276 else {
12277 xmlSchemaTypePtr circ;
12278
12279 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12280 if (circ != NULL) {
12281 /*
12282 * TODO: Report the referenced attr group as QName.
12283 */
12284 xmlSchemaPCustomErr(ctxt,
12285 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12286 NULL, NULL, circ->node,
12287 "Circular reference to the model group definition '%s' "
12288 "defined", modelGrDef->name);
12289 /*
12290 * NOTE: We will cut the reference to avoid further
12291 * confusion of the processor.
12292 * TODO: SPEC: Does the spec define how to process here?
12293 */
12294 circ->subtypes = NULL;
12295 }
12296 }
12297}
12298
12299
12300/**
12301 * xmlSchemaGetCircAttrGrRef:
12302 * @ctxtGr: the searched attribute group
12303 * @attr: the current attribute list to be processed
12304 *
12305 * This one is intended to be used by
12306 * xmlSchemaCheckSRCAttributeGroupCircular only.
12307 *
12308 * Returns the circular attribute grou reference, otherwise NULL.
12309 */
12310static xmlSchemaAttributeGroupPtr
12311xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12312 xmlSchemaAttributePtr attr)
12313{
12314 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12315 int marked;
12316 /*
12317 * We will search for an attribute group reference which
12318 * references the context attribute group.
12319 */
12320 while (attr != NULL) {
12321 marked = 0;
12322 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12323 gr = (xmlSchemaAttributeGroupPtr) attr;
12324 if (gr->refItem != NULL) {
12325 if (gr->refItem == ctxtGr)
12326 return (gr);
12327 else if (gr->refItem->flags &
12328 XML_SCHEMAS_ATTRGROUP_MARKED) {
12329 attr = attr->next;
12330 continue;
12331 } else {
12332 /*
12333 * Mark as visited to avoid infinite recursion on
12334 * circular references not yet examined.
12335 */
12336 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12337 marked = 1;
12338 }
12339 }
12340 if (gr->attributes != NULL)
12341 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
12342 /*
12343 * Unmark the visited group's attributes.
12344 */
12345 if (marked)
12346 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
12347 if (circ != NULL)
12348 return (circ);
12349 }
12350 attr = attr->next;
12351 }
12352 return (NULL);
12353}
12354
12355/**
12356 * xmlSchemaCheckSRCAttributeGroupCircular:
12357 * attrGr: the attribute group definition
12358 * @ctxt: the parser context
12359 * @name: the name
12360 *
12361 * Checks for circular references of attribute groups.
12362 */
12363static void
12364xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
12365 xmlSchemaParserCtxtPtr ctxt,
12366 const xmlChar * name ATTRIBUTE_UNUSED)
12367{
12368 /*
12369 * Schema Representation Constraint:
12370 * Attribute Group Definition Representation OK
12371 * 3 Circular group reference is disallowed outside <redefine>.
12372 * That is, unless this element information item's parent is
12373 * <redefine>, then among the [children], if any, there must
12374 * not be an <attributeGroup> with ref [attribute] which resolves
12375 * to the component corresponding to this <attributeGroup>. Indirect
12376 * circularity is also ruled out. That is, when QName resolution
12377 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
12378 * any <attributeGroup>s with a ref [attribute] among the [children],
12379 * it must not be the case that a ·QName· is encountered at any depth
12380 * which resolves to the component corresponding to this <attributeGroup>.
12381 */
12382 /*
12383 * Only global components can be referenced.
12384 */
12385 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
12386 (attrGr->attributes == NULL))
12387 return;
12388 else {
12389 xmlSchemaAttributeGroupPtr circ;
12390
12391 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
12392 if (circ != NULL) {
12393 /*
12394 * TODO: Report the referenced attr group as QName.
12395 */
12396 xmlSchemaPCustomErr(ctxt,
12397 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
12398 NULL, NULL, circ->node,
12399 "Circular reference to the attribute group '%s' "
12400 "defined", attrGr->name);
12401 /*
12402 * NOTE: We will cut the reference to avoid further
12403 * confusion of the processor.
12404 * BADSPEC: The spec should define how to process in this case.
12405 */
12406 circ->attributes = NULL;
12407 circ->refItem = NULL;
12408 }
12409 }
12410}
12411
12412/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000012413 * xmlSchemaAttrGrpFixup:
12414 * @attrgrpDecl: the schema attribute definition
12415 * @ctxt: the schema parser context
12416 * @name: the attribute name
12417 *
12418 * Fixes finish doing the computations on the attributes definitions
12419 */
12420static void
Daniel Veillard3646d642004-06-02 19:19:14 +000012421xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012422 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000012423{
12424 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012425 name = attrgrp->name;
12426 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012427 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000012428 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012429 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000012430
Daniel Veillardc0826a72004-08-10 14:17:33 +000012431 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
12432 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012433 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012434 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012435 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012436 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
12437 "ref", attrgrp->ref, attrgrp->refNs,
12438 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012439 return;
12440 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012441 attrgrp->refItem = ref;
12442 /*
12443 * Check for self reference!
12444 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012445 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012446 attrgrp->attributes = ref->attributes;
12447 attrgrp->attributeWildcard = ref->attributeWildcard;
12448 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000012449}
12450
12451/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012452 * xmlSchemaAttrFixup:
12453 * @attrDecl: the schema attribute definition
12454 * @ctxt: the schema parser context
12455 * @name: the attribute name
12456 *
12457 * Fixes finish doing the computations on the attributes definitions
12458 */
12459static void
12460xmlSchemaAttrFixup(xmlSchemaAttributePtr attrDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012461 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012462{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012463 /*
12464 * TODO: If including this is done twice (!) for every attribute.
12465 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012466 /*
12467 * The simple type definition corresponding to the <simpleType> element
12468 * information item in the [children], if present, otherwise the simple
12469 * type definition ·resolved· to by the ·actual value· of the type
12470 * [attribute], if present, otherwise the ·simple ur-type definition·.
12471 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012472 if (attrDecl->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
12473 return;
12474 attrDecl->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000012475 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012476 name = attrDecl->name;
Daniel Veillard4255d502002-04-16 15:50:10 +000012477 if (attrDecl->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012478 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012479 if (attrDecl->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012480 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012481
Daniel Veillard01fa6152004-06-29 17:04:39 +000012482 type = xmlSchemaGetType(ctxt->schema, attrDecl->typeName,
12483 attrDecl->typeNs);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012484 if ((type == NULL) ||
12485 ((type->type != XML_SCHEMA_TYPE_SIMPLE) &&
12486 (type->type != XML_SCHEMA_TYPE_BASIC)) ||
12487 ((type->type == XML_SCHEMA_TYPE_BASIC) &&
12488 (type->builtInType == XML_SCHEMAS_ANYTYPE))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012489 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012491 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
12492 "type", attrDecl->typeName, attrDecl->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012493 XML_SCHEMA_TYPE_SIMPLE, NULL);
12494 } else
12495 attrDecl->subtypes = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000012496 } else if (attrDecl->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012497 xmlSchemaAttributePtr ref;
Daniel Veillard4255d502002-04-16 15:50:10 +000012498
Daniel Veillardc0826a72004-08-10 14:17:33 +000012499 /*
12500 * TODO: Evaluate, what errors could occur if the declaration is not
12501 * found. It might be possible that the "typefixup" might crash if
12502 * no ref declaration was found.
12503 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012504 ref = xmlSchemaGetAttribute(ctxt->schema, attrDecl->ref, attrDecl->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012505 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012506 xmlSchemaPResCompAttrErr(ctxt,
12507 XML_SCHEMAP_SRC_RESOLVE,
12508 NULL, (xmlSchemaTypePtr) attrDecl, attrDecl->node,
12509 "ref", attrDecl->ref, attrDecl->refNs,
12510 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012511 return;
12512 }
12513 xmlSchemaAttrFixup(ref, ctxt, NULL);
12514 attrDecl->subtypes = ref->subtypes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012515 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012516 attrDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
Daniel Veillard4255d502002-04-16 15:50:10 +000012517 }
12518}
12519
12520/**
12521 * xmlSchemaParse:
12522 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000012523 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000012524 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000012525 * XML Shema struture which can be used to validate instances.
12526 * *WARNING* this interface is highly subject to change
12527 *
12528 * Returns the internal XML Schema structure built from the resource or
12529 * NULL in case of error
12530 */
12531xmlSchemaPtr
12532xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
12533{
12534 xmlSchemaPtr ret = NULL;
12535 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012536 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012537 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012538
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012539 /*
12540 * This one is used if the schema to be parsed was specified via
12541 * the API; i.e. not automatically by the validated instance document.
12542 */
12543
Daniel Veillard4255d502002-04-16 15:50:10 +000012544 xmlSchemaInitTypes();
12545
Daniel Veillard6045c902002-10-09 21:13:59 +000012546 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000012547 return (NULL);
12548
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012549 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012550 ctxt->counter = 0;
12551 ctxt->container = NULL;
12552
12553 /*
12554 * First step is to parse the input document into an DOM/Infoset
12555 */
Daniel Veillard6045c902002-10-09 21:13:59 +000012556 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012557 doc = xmlReadFile((const char *) ctxt->URL, NULL,
12558 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012559 if (doc == NULL) {
12560 xmlSchemaPErr(ctxt, NULL,
12561 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012562 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012563 ctxt->URL, NULL);
12564 return (NULL);
12565 }
Daniel Veillard6045c902002-10-09 21:13:59 +000012566 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012567 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
12568 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012569 if (doc == NULL) {
12570 xmlSchemaPErr(ctxt, NULL,
12571 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012572 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012573 NULL, NULL);
12574 return (NULL);
12575 }
12576 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000012577 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000012578 } else if (ctxt->doc != NULL) {
12579 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012580 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000012581 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012582 xmlSchemaPErr(ctxt, NULL,
12583 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012584 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012585 NULL, NULL);
12586 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012587 }
12588
12589 /*
12590 * Then extract the root and Schema parse it
12591 */
12592 root = xmlDocGetRootElement(doc);
12593 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012594 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
12595 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012596 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000012597 if (!preserve) {
12598 xmlFreeDoc(doc);
12599 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012600 return (NULL);
12601 }
12602
12603 /*
12604 * Remove all the blank text nodes
12605 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012606 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000012607
12608 /*
12609 * Then do the parsing for good
12610 */
12611 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000012612 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000012613 if (!preserve) {
12614 xmlFreeDoc(doc);
12615 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012616 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000012617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012618 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012619 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000012620 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012621 ctxt->ctxtType = NULL;
12622 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012623 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000012624 * Then fixup all attributes declarations
12625 */
12626 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
12627
12628 /*
12629 * Then fixup all attributes group declarations
12630 */
12631 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
12632 ctxt);
12633
12634 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012635 * Check attribute groups for circular references.
12636 */
12637 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
12638 xmlSchemaCheckAttributeGroupCircular, ctxt);
12639
12640 /*
12641 * Then fixup all model group definitions.
12642 */
12643 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012644
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012645 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000012646 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000012647 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012648 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649
12650 /*
12651 * Then fix references of element declaration; apply constraints.
12652 */
12653 xmlHashScanFull(ret->elemDecl,
12654 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012655
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012656 /*
12657 * Check model groups defnitions for circular references.
12658 */
12659 xmlHashScan(ret->groupDecl, (xmlHashScanner)
12660 xmlSchemaCheckGroupDefCircular, ctxt);
12661
Daniel Veillard4255d502002-04-16 15:50:10 +000012662 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012663 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000012664 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012665 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012666 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012667
12668 /*
12669 * Then check the defaults part of the type like facets values
12670 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012671 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
12672 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012673
Daniel Veillardc0826a72004-08-10 14:17:33 +000012674
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012675 if (ctxt->nberrors != 0) {
12676 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012677 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012678 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012679 return (ret);
12680}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012681
Daniel Veillard4255d502002-04-16 15:50:10 +000012682/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000012683 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000012684 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000012685 * @err: the error callback
12686 * @warn: the warning callback
12687 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000012688 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000012689 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000012690 */
12691void
12692xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012693 xmlSchemaValidityErrorFunc err,
12694 xmlSchemaValidityWarningFunc warn, void *ctx)
12695{
Daniel Veillard4255d502002-04-16 15:50:10 +000012696 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012697 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012698 ctxt->error = err;
12699 ctxt->warning = warn;
12700 ctxt->userData = ctx;
12701}
12702
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012703/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000012704 * xmlSchemaGetParserErrors:
12705 * @ctxt: a XMl-Schema parser context
12706 * @err: the error callback result
12707 * @warn: the warning callback result
12708 * @ctx: contextual data for the callbacks result
12709 *
12710 * Get the callback information used to handle errors for a parser context
12711 *
12712 * Returns -1 in case of failure, 0 otherwise
12713 */
12714int
12715xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
12716 xmlSchemaValidityErrorFunc * err,
12717 xmlSchemaValidityWarningFunc * warn, void **ctx)
12718{
12719 if (ctxt == NULL)
12720 return(-1);
12721 if (err != NULL)
12722 *err = ctxt->error;
12723 if (warn != NULL)
12724 *warn = ctxt->warning;
12725 if (ctx != NULL)
12726 *ctx = ctxt->userData;
12727 return(0);
12728}
12729
12730/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012731 * xmlSchemaFacetTypeToString:
12732 * @type: the facet type
12733 *
12734 * Convert the xmlSchemaTypeType to a char string.
12735 *
12736 * Returns the char string representation of the facet type if the
12737 * type is a facet and an "Internal Error" string otherwise.
12738 */
12739static const char *
12740xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
12741{
12742 switch (type) {
12743 case XML_SCHEMA_FACET_PATTERN:
12744 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012745 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012746 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012747 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012748 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012749 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012750 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012751 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012752 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012754 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012756 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012758 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012759 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012760 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012761 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012762 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012763 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012764 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012766 return ("fractionDigits");
12767 default:
12768 break;
12769 }
12770 return ("Internal Error");
12771}
12772
Daniel Veillardc0826a72004-08-10 14:17:33 +000012773static xmlChar *
12774xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
12775 const xmlChar *cur = value;
12776 xmlChar *ret = NULL, *mcur;
12777
12778 if (value == NULL)
12779 return(NULL);
12780
12781 while ((*cur != 0) &&
12782 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
12783 cur++;
12784 }
12785 if (*cur == 0)
12786 return (NULL);
12787 ret = xmlStrdup(value);
12788 /* TODO FIXME: I guess gcc will bark at this. */
12789 mcur = (xmlChar *) (ret + (cur - value));
12790 do {
12791 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
12792 *mcur = ' ';
12793 mcur++;
12794 } while (*mcur != 0);
12795 return(ret);
12796}
12797
12798static int
12799xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
12800{
12801 xmlSchemaTypePtr anc;
12802
12803 /*
12804 * The normalization type can be changed only for types which are derived
12805 * from xsd:string.
12806 */
12807 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12808 if ((type->builtInType == XML_SCHEMAS_STRING) &&
12809 (type->builtInType == XML_SCHEMAS_NORMSTRING))
12810
12811 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12812 else {
12813 /*
12814 * For all ·atomic· datatypes other than string (and types ·derived·
12815 * by ·restriction· from it) the value of whiteSpace is fixed to
12816 * collapse
12817 */
12818 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12819 }
12820 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12821 /*
12822 * For list types the facet "whiteSpace" is fixed to "collapse".
12823 */
12824 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12825 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12826 return (-1);
12827 } else if (type->facetSet != NULL) {
12828 xmlSchemaTypePtr anyST;
12829 xmlSchemaFacetLinkPtr lin;
12830
12831 /*
12832 * Atomic types.
12833 */
12834 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12835 anc = type->baseType;
12836 do {
12837 /*
12838 * For all ·atomic· datatypes other than string (and types ·derived·
12839 * by ·restriction· from it) the value of whiteSpace is fixed to
12840 * collapse
12841 */
12842 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
12843 (anc->builtInType == XML_SCHEMAS_STRING)) {
12844
12845 lin = type->facetSet;
12846 do {
12847 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
12848 if (lin->facet->whitespace ==
12849 XML_SCHEMAS_FACET_COLLAPSE) {
12850 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12851 } else if (lin->facet->whitespace ==
12852 XML_SCHEMAS_FACET_REPLACE) {
12853 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
12854 } else
12855 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12856 break;
12857 }
12858 lin = lin->next;
12859 } while (lin != NULL);
12860 break;
12861 }
12862 anc = anc->baseType;
12863 } while (anc != anyST);
12864 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12865 }
12866 return (-1);
12867}
12868
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012869/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000012870 * xmlSchemaValidateFacetsInternal:
12871 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000012872 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000012873 * @facets: the list of facets to check
12874 * @value: the lexical repr of the value to validate
12875 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000012876 * @fireErrors: if 0, only internal errors will be fired;
12877 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000012878 *
12879 * Check a value against all facet conditions
12880 *
12881 * Returns 0 if the element is schemas valid, a positive error code
12882 * number otherwise and -1 in case of internal or API error.
12883 */
12884static int
12885xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012886 xmlSchemaTypePtr type,
12887 const xmlChar * value,
12888 unsigned long length,
12889 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012890{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012891 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012892 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012893 xmlSchemaTypePtr biType; /* The build-in type. */
12894 xmlSchemaTypePtr tmpType;
12895 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000012896 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012897 xmlSchemaFacetPtr facet;
12898 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012899
Daniel Veillardc0826a72004-08-10 14:17:33 +000012900#ifdef DEBUG_UNION_VALIDATION
12901 printf("Facets of type: '%s'\n", (const char *) type->name);
12902 printf(" fireErrors: %d\n", fireErrors);
12903#endif
12904
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012905 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012906 /*
12907 * NOTE: Do not jump away, if the facetSet of the given type is
12908 * empty: until now, "pattern" facets of the *base types* need to
12909 * be checked as well.
12910 */
12911 biType = type->baseType;
12912 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12913 biType = biType->baseType;
12914 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012915 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012916 "Internal error: xmlSchemaValidateFacetsInternal, "
12917 "the base type axis of the given type '%s' does not resolve to "
12918 "a built-in type.\n",
12919 type->name, NULL);
12920 return (-1);
12921 }
12922
12923 if (type->facetSet != NULL) {
12924 facetLink = type->facetSet;
12925 while (facetLink != NULL) {
12926 facet = facetLink->facet;
12927 /*
12928 * Skip the pattern "whiteSpace": it is used to
12929 * format the character content beforehand.
12930 */
12931 switch (facet->type) {
12932 case XML_SCHEMA_FACET_WHITESPACE:
12933 case XML_SCHEMA_FACET_PATTERN:
12934 case XML_SCHEMA_FACET_ENUMERATION:
12935 break;
12936 case XML_SCHEMA_FACET_LENGTH:
12937 case XML_SCHEMA_FACET_MINLENGTH:
12938 case XML_SCHEMA_FACET_MAXLENGTH:
12939 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12940 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12941 value, length, 0);
12942 len = length;
12943 } else
12944 ret = xmlSchemaValidateLengthFacet(biType, facet,
12945 value, ctxt->value, &len);
12946 break;
12947 default:
12948 ret = xmlSchemaValidateFacet(biType, facet, value,
12949 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012950 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012951 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012952 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012953 "Internal error: xmlSchemaValidateFacetsInternal, "
12954 "validating facet of type '%s'.\n",
12955 type->name, NULL);
12956 break;
12957 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012958 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012959 type, facet, NULL, NULL, NULL, NULL);
12960 }
12961
12962 facetLink = facetLink->next;
12963 }
12964 if (ret >= 0) {
12965 /*
12966 * Process enumerations.
12967 */
12968 retFacet = 0;
12969 facetLink = type->facetSet;
12970 while (facetLink != NULL) {
12971 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12972 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12973 value, ctxt->value);
12974 if (retFacet <= 0)
12975 break;
12976 }
12977 facetLink = facetLink->next;
12978 }
12979 if (retFacet > 0) {
12980 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12981 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012982 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012983 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12984 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012985 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012986 "Internal error: xmlSchemaValidateFacetsInternal, "
12987 "validating facet of type '%s'.\n",
12988 BAD_CAST "enumeration", NULL);
12989 ret = -1;
12990 }
12991 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012992 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012993 if (ret >= 0) {
12994 /*
12995 * Process patters. Pattern facets are ORed at type level
12996 * and ANDed if derived. Walk the base type axis.
12997 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012998 tmpType = type;
12999 facet = NULL;
13000 do {
13001 retFacet = 0;
13002 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013003 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013004 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13005 continue;
13006 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13007 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013008 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013009 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013010 else if (retFacet < 0) {
13011 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13012 "Internal error: xmlSchemaValidateFacetsInternal, "
13013 "validating 'pattern' facet '%s' of type '%s'.\n",
13014 facetLink->facet->value, tmpType->name);
13015 ret = -1;
13016 break;
13017 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013018 /* Save the last non-validating facet. */
13019 facet = facetLink->facet;
13020 }
13021 if (retFacet != 0)
13022 break;
13023 tmpType = tmpType->baseType;
13024 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013025 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013026 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13027 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013028 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013029 NULL, NULL, NULL, NULL);
13030 }
13031 }
13032 }
13033
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013034 return (ret);
13035}
13036
Daniel Veillard4255d502002-04-16 15:50:10 +000013037/************************************************************************
13038 * *
13039 * Simple type validation *
13040 * *
13041 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013042
Daniel Veillard4255d502002-04-16 15:50:10 +000013043
13044/************************************************************************
13045 * *
13046 * DOM Validation code *
13047 * *
13048 ************************************************************************/
13049
Daniel Veillard4255d502002-04-16 15:50:10 +000013050static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013051 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013052 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013053static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
13054 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000013055
Daniel Veillard3646d642004-06-02 19:19:14 +000013056
13057/**
13058 * xmlSchemaFreeAttrStates:
13059 * @state: a list of attribute states
13060 *
13061 * Free the given list of attribute states
13062 *
13063 */
13064static void
13065xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13066{
13067 xmlSchemaAttrStatePtr tmp;
13068 while (state != NULL) {
13069 tmp = state;
13070 state = state->next;
13071 xmlFree(tmp);
13072 }
13073}
13074
Daniel Veillard4255d502002-04-16 15:50:10 +000013075/**
13076 * xmlSchemaRegisterAttributes:
13077 * @ctxt: a schema validation context
13078 * @attrs: a list of attributes
13079 *
13080 * Register the list of attributes as the set to be validated on that element
13081 *
13082 * Returns -1 in case of error, 0 otherwise
13083 */
13084static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013085xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13086{
Daniel Veillard3646d642004-06-02 19:19:14 +000013087 xmlSchemaAttrStatePtr tmp;
13088
13089 ctxt->attr = NULL;
13090 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013091 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013092 if ((attrs->ns != NULL) &&
13093 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13094 attrs = attrs->next;
13095 continue;
13096 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013097 tmp = (xmlSchemaAttrStatePtr)
13098 xmlMalloc(sizeof(xmlSchemaAttrState));
13099 if (tmp == NULL) {
13100 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13101 return (-1);
13102 }
Daniel Veillard079f6a72004-09-23 13:15:03 +000013103 memset(tmp, 0, sizeof(xmlSchemaAttrState));
Daniel Veillard3646d642004-06-02 19:19:14 +000013104 tmp->attr = attrs;
13105 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13106 tmp->next = NULL;
13107 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013108 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013109 else
13110 ctxt->attrTop->next = tmp;
13111 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013112 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013113 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013114 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013115}
13116
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013117#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013118/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013119 * xmlSchemaValidateCheckNodeList
13120 * @nodelist: the list of nodes
13121 *
13122 * Check the node list is only made of text nodes and entities pointing
13123 * to text nodes
13124 *
13125 * Returns 1 if true, 0 if false and -1 in case of error
13126 */
13127static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013128xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13129{
Daniel Veillard4255d502002-04-16 15:50:10 +000013130 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013131 if (nodelist->type == XML_ENTITY_REF_NODE) {
13132 TODO /* implement recursion in the entity content */
13133 }
13134 if ((nodelist->type != XML_TEXT_NODE) &&
13135 (nodelist->type != XML_COMMENT_NODE) &&
13136 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013137 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013138 return (0);
13139 }
13140 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013141 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013142 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013143}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013144#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013145
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013146static void
13147xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
13148{
13149 int i, nbItems;
13150 xmlSchemaTypePtr item, *items;
13151
13152
13153 /*
13154 * During the Assemble of the schema ctxt->curItems has
13155 * been filled with the relevant new items. Fix those up.
13156 */
13157 nbItems = ctxt->assemble->nbItems;
13158 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
13159
13160 for (i = 0; i < nbItems; i++) {
13161 item = items[i];
13162 switch (item->type) {
13163 case XML_SCHEMA_TYPE_ATTRIBUTE:
13164 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
13165 break;
13166 case XML_SCHEMA_TYPE_ELEMENT:
13167 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
13168 NULL, NULL, NULL);
13169 break;
13170 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13171 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
13172 ctxt, NULL);
13173 break;
13174 case XML_SCHEMA_TYPE_GROUP:
13175 xmlSchemaGroupDefFixup(item, ctxt, NULL);
13176 default:
13177 break;
13178 }
13179 }
13180 /*
13181 * Circularity checks.
13182 */
13183 for (i = 0; i < nbItems; i++) {
13184 item = items[i];
13185 switch (item->type) {
13186 case XML_SCHEMA_TYPE_GROUP:
13187 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
13188 break;
13189 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13190 xmlSchemaCheckAttributeGroupCircular(
13191 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
13192 break;
13193 default:
13194 break;
13195 }
13196 }
13197 /*
13198 * Fixup for all other item.
13199 * TODO: Hmm, not sure if starting from complex/simple types,
13200 * all subsequent items will be reached.
13201 */
13202 for (i = 0; i < nbItems; i++) {
13203 item = items[i];
13204 switch (item->type) {
13205 case XML_SCHEMA_TYPE_SIMPLE:
13206 case XML_SCHEMA_TYPE_COMPLEX:
13207 xmlSchemaTypeFixup(item, ctxt, NULL);
13208 break;
13209 default:
13210 break;
13211 }
13212 }
13213 /*
13214 * Check facet values. Note that facets are
13215 * hold by complex and simple type components only.
13216 */
13217 for (i = 0; i < nbItems; i++) {
13218 item = items[i];
13219 switch (item->type) {
13220 case XML_SCHEMA_TYPE_SIMPLE:
13221 case XML_SCHEMA_TYPE_COMPLEX:
13222 xmlSchemaCheckDefaults(item, ctxt, NULL);
13223 break;
13224 default:
13225 break;
13226 }
13227 }
13228 /*
13229 * Build the content model for complex types.
13230 */
13231 for (i = 0; i < nbItems; i++) {
13232 item = items[i];
13233 switch (item->type) {
13234 case XML_SCHEMA_TYPE_COMPLEX:
13235 xmlSchemaBuildContentModel(item, ctxt, NULL);
13236 break;
13237 default:
13238 break;
13239 }
13240 }
13241}
13242
13243/**
13244 * xmlSchemaAssembleByLocation:
13245 * @pctxt: a schema parser context
13246 * @vctxt: a schema validation context
13247 * @schema: the existing schema
13248 * @node: the node that fired the assembling
13249 * @nsName: the namespace name of the new schema
13250 * @location: the location of the schema
13251 *
13252 * Expands an existing schema by an additional schema.
13253 *
13254 * Returns 0 if the new schema is correct, a positive error code
13255 * number otherwise and -1 in case of an internal or API error.
13256 */
13257static int
13258xmlSchemaAssembleByLocation(xmlSchemaParserCtxtPtr pctxt,
13259 xmlSchemaValidCtxtPtr vctxt,
13260 xmlSchemaPtr schema,
13261 xmlNodePtr node,
13262 const xmlChar *nsName,
13263 const xmlChar *location)
13264{
13265 const xmlChar *targetNs, *oldtns;
13266 xmlDocPtr doc, olddoc;
13267 int oldflags, ret = 0, reuseCtxt;
13268 xmlNodePtr docElem;
13269 /*
13270 * This should be used:
13271 * 1. on <import>(s)
13272 * 2. if requested by the validated instance
13273 * 3. if requested via the API
13274 */
13275 if ((pctxt == NULL) && (vctxt == NULL))
13276 return (-1);
13277 /*
13278 * Create a temporary parser context.
13279 * TODO: what to set exaclty for the URL argument here?
13280 */
13281 if (pctxt == NULL) {
13282 reuseCtxt = 0;
13283 pctxt = xmlSchemaNewParserCtxtUseDict((const char *) location, schema->dict);
13284 if (pctxt == NULL) {
13285 xmlSchemaVErrMemory(vctxt,
13286 "xmlSchemaAssembleByLocation, allocating new parser "
13287 "content for dynamic construction of schemata", NULL);
13288 return (-1);
13289 }
13290 pctxt->error = vctxt->error;
13291 pctxt->warning = vctxt->warning;
13292 } else
13293 reuseCtxt = 1;
13294 /*
13295 * Acquire the schema document.
13296 */
13297 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
13298 nsName, location, &doc, &targetNs, 0);
13299 if (ret != 0) {
13300 if (doc != NULL)
13301 xmlFreeDoc(doc);
13302 } else if (doc != NULL) {
13303 docElem = xmlDocGetRootElement(doc);
13304 /*
13305 * Save and reset the context & schema.
13306 */
13307 oldflags = schema->flags;
13308 oldtns = schema->targetNamespace;
13309 olddoc = schema->doc;
13310
13311 xmlSchemaClearSchemaDefaults(schema);
13312 schema->targetNamespace = targetNs;
13313 /* schema->nbCurItems = 0; */
13314 pctxt->schema = schema;
13315 if (pctxt->assemble == NULL) {
13316 pctxt->assemble = xmlSchemaNewAssemble();
13317 xmlSchemaVErrMemory(vctxt,
13318 "Memory error: xmlSchemaAssembleByLocation, "
13319 "allocating assemble info", NULL);
13320 return (-1);
13321 }
13322 pctxt->ctxtType = NULL;
13323 pctxt->parentItem = NULL;
13324
13325 xmlSchemaParseSchemaDefaults(pctxt, pctxt->schema, docElem);
13326 xmlSchemaParseSchemaTopLevel(pctxt, pctxt->schema, docElem->children);
13327 xmlSchemaPostSchemaAssembleFixup(pctxt);
13328 /*
13329 * Free the list of assembled components.
13330 */
13331 xmlFree(pctxt->assemble->items);
13332 /*
13333 * Restore the context & schema.
13334 */
13335 schema->flags = oldflags;
13336 schema->targetNamespace = oldtns;
13337 schema->doc = olddoc;
13338 ret = pctxt->err;
13339 }
13340 if (reuseCtxt == 0) {
13341 pctxt->dict = NULL;
13342 xmlSchemaFreeParserCtxt(pctxt);
13343 }
13344 return (ret);
13345}
13346
13347/**
13348 * xmlSchemaAssembleByXSIAttr:
13349 * @vctxt: a schema validation context
13350 * @xsiAttr: an xsi attribute
13351 * @noNamespace: whether a schema with no target namespace is exptected
13352 *
13353 * Expands an existing schema by an additional schema using
13354 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
13355 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
13356 * must be set to 1.
13357 *
13358 * Returns 0 if the new schema is correct, a positive error code
13359 * number otherwise and -1 in case of an internal or API error.
13360 */
13361static int
13362xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
13363 xmlAttrPtr xsiAttr,
13364 int noNamespace)
13365{
13366 xmlChar *value;
13367 const xmlChar *cur, *end;
13368 const xmlChar *nsname = NULL, *location;
13369 int count = 0;
13370 int ret = 0;
13371
13372 if (xsiAttr == NULL) {
13373 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
13374 NULL, NULL,
13375 "Internal error: xmlSchemaAssembleByXSIAttr, "
13376 "bad arguments", NULL);
13377 return (-1);
13378 }
13379 /*
13380 * Parse the value; we will assume an even number of values
13381 * to be given (this is how Xerces and XSV work).
13382 */
13383 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
13384 cur = value;
13385 do {
13386 if (noNamespace != 1) {
13387 /*
13388 * Get the namespace name.
13389 */
13390 while (IS_BLANK_CH(*cur))
13391 cur++;
13392 end = cur;
13393 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13394 end++;
13395 if (end == cur)
13396 break;
13397 count++;
13398 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
13399 cur = end;
13400 }
13401 /*
13402 * Get the URI.
13403 */
13404 while (IS_BLANK_CH(*cur))
13405 cur++;
13406 end = cur;
13407 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13408 end++;
13409 if (end == cur)
13410 break;
13411 count++;
13412 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
13413 cur = end;
13414 ret = xmlSchemaAssembleByLocation(NULL, vctxt, vctxt->schema,
13415 xsiAttr->parent, nsname, location);
13416 if (ret == -1) {
13417 xmlSchemaVCustomErr(vctxt,
13418 XML_SCHEMAV_INTERNAL,
13419 (xmlNodePtr) xsiAttr, NULL,
13420 "Internal error: xmlSchemaAssembleByXSIAttr, "
13421 "assembling schemata", NULL);
13422 if (value != NULL)
13423 xmlFree(value);
13424 return (-1);
13425 }
13426 } while (*cur != 0);
13427 if (value != NULL)
13428 xmlFree(value);
13429 return (ret);
13430}
13431
13432/**
13433 * xmlSchemaAssembleByXSIElem:
13434 * @vctxt: a schema validation context
13435 * @elem: an element node possibly holding xsi attributes
13436 * @noNamespace: whether a schema with no target namespace is exptected
13437 *
13438 * Assembles an existing schema by an additional schema using
13439 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
13440 * of the given @elem.
13441 *
13442 * Returns 0 if the new schema is correct, a positive error code
13443 * number otherwise and -1 in case of an internal or API error.
13444 */
13445static int
13446xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
13447 xmlNodePtr elem)
13448{
13449 int ret = 0, retNs = 0;
13450 xmlAttrPtr attr;
13451
13452 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
13453 if (attr != NULL) {
13454 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
13455 if (retNs == -1)
13456 return (-1);
13457 }
13458 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
13459 if (attr != NULL) {
13460 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
13461 if (ret == -1)
13462 return (-1);
13463 }
13464 if (retNs != 0)
13465 return (retNs);
13466 else
13467 return (ret);
13468}
13469
Daniel Veillard4255d502002-04-16 15:50:10 +000013470/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013471 * xmlSchemaValidateCallback:
13472 * @ctxt: a schema validation context
13473 * @name: the name of the element detected (might be NULL)
13474 * @type: the type
13475 *
13476 * A transition has been made in the automata associated to an element
13477 * content model
13478 */
13479static void
13480xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013481 const xmlChar * name ATTRIBUTE_UNUSED,
13482 xmlSchemaTypePtr type, xmlNodePtr node)
13483{
Daniel Veillard4255d502002-04-16 15:50:10 +000013484 xmlSchemaTypePtr oldtype = ctxt->type;
13485 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013486
Daniel Veillard4255d502002-04-16 15:50:10 +000013487#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000013488 xmlGenericError(xmlGenericErrorContext,
13489 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013490 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013491#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013492 /*
13493 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
13494 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013495 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013496 ctxt->node = node;
13497 ctxt->cur = node->children;
13498 /*
13499 * Assemble new schemata using xsi.
13500 */
13501 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
13502 int ret;
13503
13504 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
13505 if (ret == -1) {
13506 xmlSchemaVCustomErr(ctxt,
13507 XML_SCHEMAV_INTERNAL,
13508 ctxt->node, NULL,
13509 "Internal error: xmlSchemaValidateElement, "
13510 "assembling schema by xsi", NULL);
13511 return;
13512 }
13513 /*
13514 * NOTE: We won't react on schema parser errors here.
13515 * TODO: But a warning would be nice.
13516 */
13517 }
13518 switch (type->type) {
13519 case XML_SCHEMA_TYPE_ELEMENT: {
13520 /*
13521 * NOTE: The build of the content model
13522 * (xmlSchemaBuildAContentModel) ensures that the element
13523 * declaration (and not a reference to it) will be given.
13524 */
13525 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
13526 /*
13527 * This is paranoid coding ;-)... it should not
13528 * happen here any more.
13529 */
13530 xmlSchemaVCustomErr(ctxt,
13531 XML_SCHEMAV_INTERNAL,
13532 node, NULL,
13533 "Internal error: xmlSchemaValidateCallback, "
13534 "element declaration 'reference' encountered, "
13535 "but an element declaration was expected",
13536 NULL);
13537 return;
13538 }
13539 xmlSchemaValidateElementByDeclaration(ctxt,
13540 (xmlSchemaElementPtr) type);
13541 break;
13542 }
13543 case XML_SCHEMA_TYPE_ANY:
13544 xmlSchemaValidateElementByWildcard(ctxt, type);
13545 break;
13546 default:
13547 break;
13548 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013549 ctxt->type = oldtype;
13550 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013551}
Daniel Veillard4255d502002-04-16 15:50:10 +000013552
Daniel Veillard01fa6152004-06-29 17:04:39 +000013553/**
13554 * xmlSchemaValidateSimpleTypeValue:
13555 * @ctxt: a schema validation context
13556 * @value: the value to be validated
13557 * @fireErrors: shall errors be reported?
13558 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000013559 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013560 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013561 *
13562 * Validates a value by the given type (user derived or built-in).
13563 *
13564 * Returns 0 if the value is valid, a positive error code
13565 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 */
13567static int
13568xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013569 xmlSchemaTypePtr type,
13570 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013571 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013572 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013573 int normalize,
13574 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013575{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013576 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013577 int ret = 0;
13578 xmlChar *normValue = NULL;
13579 int wtsp;
13580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013581 node = ctxt->node;
13582 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013583 wtsp = ctxt->valueWS;
13584 /*
13585 * Normalize the value.
13586 */
13587 if (normalize &&
13588 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
13589 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
13590
13591 if ((norm != -1) && (norm > ctxt->valueWS)) {
13592 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
13593 normValue = xmlSchemaCollapseString(value);
13594 else
13595 normValue = xmlSchemaWhiteSpaceReplace(value);
13596 ctxt->valueWS = norm;
13597 if (normValue != NULL)
13598 value = (const xmlChar *) normValue;
13599 }
13600 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013601 /*
13602 * The nodes of a content must be checked only once,
13603 * this is not working since list types will fire this
13604 * multiple times.
13605 */
13606 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
13607 xmlNodePtr cur = ctxt->cur;
13608
13609 do {
13610 switch (cur->type) {
13611 case XML_TEXT_NODE:
13612 case XML_CDATA_SECTION_NODE:
13613 case XML_PI_NODE:
13614 case XML_COMMENT_NODE:
13615 case XML_XINCLUDE_START:
13616 case XML_XINCLUDE_END:
13617 break;
13618 case XML_ENTITY_REF_NODE:
13619 case XML_ENTITY_NODE:
13620 /* TODO: Scour the entities for illegal nodes. */
13621 TODO break;
13622 case XML_ELEMENT_NODE: {
13623 /* NOTE: Changed to an internal error, since the
13624 * existence of an element node will be already checked in
13625 * xmlSchemaValidateElementBySimpleType and in
13626 * xmlSchemaValidateElementByComplexType.
13627 */
13628 xmlSchemaVCustomErr(ctxt,
13629 XML_SCHEMAV_INTERNAL,
13630 /* XML_SCHEMAS_ERR_INVALIDELEM, */
13631 node, type,
13632 "Element '%s' found in simple type content",
13633 cur->name);
13634 return (XML_SCHEMAV_INTERNAL);
13635 }
13636 case XML_ATTRIBUTE_NODE:
13637 case XML_DOCUMENT_NODE:
13638 case XML_DOCUMENT_TYPE_NODE:
13639 case XML_DOCUMENT_FRAG_NODE:
13640 case XML_NOTATION_NODE:
13641 case XML_HTML_DOCUMENT_NODE:
13642 case XML_DTD_NODE:
13643 case XML_ELEMENT_DECL:
13644 case XML_ATTRIBUTE_DECL:
13645 case XML_ENTITY_DECL:
13646 case XML_NAMESPACE_DECL:
13647#ifdef LIBXML_DOCB_ENABLED
13648 case XML_DOCB_DOCUMENT_NODE:
13649#endif
13650 xmlSchemaVCustomErr(ctxt,
13651 XML_SCHEMAV_INTERNAL,
13652 /* XML_SCHEMAS_ERR_INVALIDELEM, */
13653 node, NULL,
13654 "Node of unexpected type found in simple type content",
13655 NULL);
13656 return (XML_SCHEMAV_INTERNAL);
13657 }
13658 cur = cur->next;
13659 } while (cur != NULL);
13660 }
13661
William M. Brack2f2a6632004-08-20 23:09:47 +000013662 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
13663 xmlSchemaTypePtr base, anyType;
13664
13665 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13666
13667 base = type->baseType;
13668 while ((base != NULL) &&
13669 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
13670 (base->type != XML_SCHEMA_TYPE_BASIC) &&
13671 (base != anyType)) {
13672 base = base->baseType;
13673 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013674 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013675 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013676 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013677 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13678 "validating complex type '%s'\n",
13679 type->name, NULL);
13680 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
13681 /*
13682 * Check facets.
13683 */
13684 /*
13685 * This is somehow not nice, since if an error occurs
13686 * the reported type will be the complex type; the spec
13687 * wants a simple type to be created on the complex type
13688 * if it has a simple content. For now we have to live with
13689 * it.
13690 */
13691 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13692 value, 0, fireErrors);
13693 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013694 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013695 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13696 "validating facets of complex type '%s'\n",
13697 type->name, NULL);
13698 } else if (ret > 0) {
13699 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000013700 if (fireErrors)
13701 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000013702 }
13703 }
13704 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013705
13706 if (ctxt->value != NULL) {
13707 xmlSchemaFreeValue(ctxt->value);
13708 ctxt->value = NULL;
13709 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013710 /*
13711 * STREAM-READ-CHILDREN.
13712 */
13713 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013714 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
13716 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
13717 else
13718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013719 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013720 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013721 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013722 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013723 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013724 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 }
13726 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13727 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
13728 * a literal in the ·lexical space· of {base type definition}
13729 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013730 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013731 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013732 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013734 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013736 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013738 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013739 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013740 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013742 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013744 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13745 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013747 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013749 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 type->name, NULL);
13751 } else if (ret > 0) {
13752 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013753 /*
13754 Disabled, since the facet validation already reports errors.
13755 if (fireErrors)
13756 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13757 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013758 }
13759 }
13760 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13761
13762 xmlSchemaTypePtr tmpType;
13763 const xmlChar *cur, *end;
13764 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013765 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766
13767 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
13768 * of white space separated tokens, each of which ·match·es a literal
13769 * in the ·lexical space· of {item type definition}
13770 */
13771
Daniel Veillardc0826a72004-08-10 14:17:33 +000013772 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 cur = value;
13774 do {
13775 while (IS_BLANK_CH(*cur))
13776 cur++;
13777 end = cur;
13778 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13779 end++;
13780 if (end == cur)
13781 break;
13782 tmp = xmlStrndup(cur, end - cur);
13783 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013784 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013787 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13789 "validating an item of list simple type '%s'\n",
13790 type->name, NULL);
13791 break;
13792 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013793 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013794 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013795 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013797 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 cur = end;
13799 } while (*cur != 0);
13800 /*
13801 * Check facets.
13802 */
13803 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013804 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013806 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 } else if ((ret == 0) && (applyFacets)) {
13809 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13810 value, len, fireErrors);
13811 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013812 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013813 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13814 "validating facets of list simple type '%s'\n",
13815 type->name, NULL);
13816 } else if (ret > 0) {
13817 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013819 Disabled, since the facet validation already reports errors.
13820 if (fireErrors)
13821 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013823 }
13824
Daniel Veillard01fa6152004-06-29 17:04:39 +000013825 }
13826 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13827 xmlSchemaTypeLinkPtr memberLink;
13828
13829 /*
13830 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
13831 * not apply directly; however, the normalization behavior of ·union·
13832 * types is controlled by the value of whiteSpace on that one of the
13833 * ·memberTypes· against which the ·union· is successfully validated.
13834 *
13835 * This means that the value is normalized by the first validating
13836 * member type, then the facets of the union type are applied. This
13837 * needs changing of the value!
13838 */
13839
13840 /*
13841 * 1.2.3 if {variety} is ·union· then the string must ·match· a
13842 * literal in the ·lexical space· of at least one member of
13843 * {member type definitions}
13844 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013845#ifdef DEBUG_UNION_VALIDATION
13846 printf("Union ST : '%s'\n", (const char *) type->name);
13847 printf(" fireErrors : %d\n", fireErrors);
13848 printf(" applyFacets: %d\n", applyFacets);
13849#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
13851 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013852 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013853 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013854 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 type->name, NULL);
13856 ret = -1;
13857 }
13858 if (ret == 0) {
13859 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013860 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
13861 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013862 if ((ret <= 0) || (ret == 0))
13863 break;
13864 memberLink = memberLink->next;
13865 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013867 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013869 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 type->name, NULL);
13871 } else if (ret > 0) {
13872 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013874 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013875 }
13876 }
13877 /*
13878 * Apply facets (pattern, enumeration).
13879 */
13880 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
13881 int mws;
13882 /*
13883 * The normalization behavior of ·union· types is controlled by
13884 * the value of whiteSpace on that one of the ·memberTypes·
13885 * against which the ·union· is successfully validated.
13886 */
13887 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013888 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013889 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13890 "the value was already normalized for the union simple "
13891 "type '%s'.\n", type->name, NULL);
13892 }
13893 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
13894 if (mws > ctxt->valueWS) {
13895 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
13896 normValue = xmlSchemaCollapseString(value);
13897 else
13898 normValue = xmlSchemaWhiteSpaceReplace(value);
13899 if (normValue != NULL)
13900 value = (const xmlChar *) normValue;
13901 }
13902
13903 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13904 value, 0, fireErrors);
13905 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013906 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013907 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13908 "validating facets of union simple type '%s'\n",
13909 type->name, NULL);
13910 } else if (ret > 0) {
13911 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
13912 /*
13913 if (fireErrors)
13914 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13915 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 }
13917 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013919 ctxt->valueWS = wtsp;
13920 if (normValue != NULL)
13921 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013922 return (ret);
13923}
13924
13925/**
13926 * xmlSchemaValidateSimpleTypeElement:
13927 * @ctxt: a schema validation context
13928 * @node: the element node to be validated.
13929 *
13930 * Validate the element against a simple type.
13931 *
13932 * Returns 0 if the element is valid, a positive error code
13933 * number otherwise and -1 in case of an internal or API error.
13934 */
13935static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013936xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
13937 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013938{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013939 xmlSchemaTypePtr oldtype;
13940 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013941 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013942 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013943 int ret = 0, retval = 0;
13944
Daniel Veillard01fa6152004-06-29 17:04:39 +000013945 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013946 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
13947 "Internal error: xmlSchemaValidateElementBySimpleType, "
13948 "bad arguments", NULL);
13949 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013950 }
13951
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013952 oldtype = ctxt->type;
13953 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013954 /*
13955 * cvc-type: 3.1.2 The element information item must have no element
13956 * information item [children].
13957 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013958 /*
13959 * STREAM: Child nodes are processed.
13960 */
13961 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013962 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013963 /*
13964 * TODO: Entities, will they produce elements as well?
13965 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013966 if (cur->type == XML_ELEMENT_NODE) {
13967 xmlSchemaVCustomErr(ctxt,
13968 XML_SCHEMAV_CVC_TYPE_3_1_2,
13969 node, type,
13970 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013971 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013972 }
13973 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013975
Daniel Veillard01fa6152004-06-29 17:04:39 +000013976 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013977 * cvc-type 3.1.1:
13978 *
13979 * The attributes of must be empty, excepting those whose namespace name
13980 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
13981 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013982 */
13983 /*
13984 * STREAM: Attribute nodes are processed.
13985 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013986 attr = node->properties;
13987 while (attr != NULL) {
13988 if ((attr->ns == NULL) ||
13989 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
13990 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
13991 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
13992 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
13993 (!xmlStrEqual
13994 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013995 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013996 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
13997 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013998 }
13999 attr = attr->next;
14000 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014001 /*
14002 * This will skip validation if the type is 'anySimpleType'.
14003 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014004 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14005 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014006 xmlChar *value;
14007
14008 value = xmlNodeGetContent(node);
14009 /*
14010 * NOTE: This call will not check the content nodes, since
14011 * this should be checked here already.
14012 */
14013 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14014 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014015 if (value != NULL)
14016 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014017 if (retval != 0)
14018 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014019 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014020 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014021 return (ret);
14022}
Daniel Veillard4255d502002-04-16 15:50:10 +000014023
14024/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014025 * xmlSchemaValQNameAcquire:
14026 * @value: the lexical represantation of the QName value
14027 * @node: the node to search for the corresponding namespace declaration
14028 * @nsName: the resulting namespace name if found
14029 *
14030 * Checks that a value conforms to the lexical space of the type QName;
14031 * if valid, the corresponding namespace name is searched and retured
14032 * as a copy in @nsName. The local name is returned in @localName as
14033 * a copy.
14034 *
14035 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14036 * namespace declaration was found in scope; -1 in case of an internal or
14037 * API error.
14038 */
14039static int
14040xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14041 xmlChar **nsName, xmlChar **localName)
14042{
14043 int ret;
14044 xmlChar *local = NULL;
14045
14046 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14047 return (-1);
14048 *nsName = NULL;
14049 *localName = NULL;
14050 ret = xmlValidateQName(value, 1);
14051 if (ret == 0) {
14052 xmlChar *prefix;
14053
14054 local = xmlSplitQName2(value, &prefix);
14055 if (prefix != NULL) {
14056 xmlNsPtr ns;
14057
14058 ns = xmlSearchNs(node->doc, node, prefix);
14059 if (ns == NULL)
14060 ret = 2;
14061 else {
14062 *nsName = xmlStrdup(ns->href);
14063 *localName = xmlStrdup(local);
14064 }
14065 }
14066 if (local != NULL)
14067 xmlFree(local);
14068 if (prefix != NULL)
14069 xmlFree(prefix);
14070 } else
14071 return (1);
14072 return (ret);
14073}
14074
14075/**
14076 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000014077 * @ctxt: a schema validation context
14078 * @node: the top node.
14079 *
14080 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014081 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000014082 *
14083 * Returns 0 if the element is schemas valid, a positive error code
14084 * number otherwise and -1 in case of internal or API error.
14085 */
14086static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014087xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
14088 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014089{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014090 xmlNodePtr elem;
Daniel Veillard3646d642004-06-02 19:19:14 +000014091 int ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014092 xmlSchemaTypePtr type = NULL;
14093 xmlAttrPtr attr;
14094 xmlChar *attrValue;
14095 int nilled = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000014096
14097 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014098 * This one is called by xmlSchemaValidateElementByWildcardInternal,
14099 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
14100 *
14101 * @ctxt->type will be the element's declaration.
14102 */
Daniel Veillard3646d642004-06-02 19:19:14 +000014103
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014104 if (ctxt == NULL) {
14105 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
14106 "Internal error: xmlSchemaValidateElementByDeclaration, "
14107 "bad arguments.\n",
14108 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014109 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014110 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014111
14112 elem = ctxt->node;
14113
14114 /*
14115 * cvc-elt (3.3.4) : 1
14116 */
14117 if (elemDecl == NULL) {
14118 xmlSchemaVCustomErr(ctxt,
14119 XML_SCHEMAV_CVC_ELT_1,
14120 elem, NULL,
14121 "No matching declaration available", NULL);
14122 return (ctxt->err);
14123 }
14124 /*
14125 * cvc-elt (3.3.4) : 2
14126 */
14127 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
14128 xmlSchemaVCustomErr(ctxt,
14129 XML_SCHEMAV_CVC_ELT_2,
14130 elem, NULL,
14131 "The element declaration is abstract", NULL);
14132 return (ctxt->err);
14133 }
14134
14135 /*
14136 * cvc-elt (3.3.4) : 3
14137 * Handle 'xsi:nil'.
14138 */
14139 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
14140 if (attr != NULL) {
14141 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
14142 ctxt->node = (xmlNodePtr) attr;
14143 ctxt->cur = attr->children;
14144 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
14145 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
14146 BAD_CAST attrValue, 1, 1, 1, 1);
14147 ctxt->node = elem;
14148 ctxt->type = (xmlSchemaTypePtr) elemDecl;
14149 if (ret < 0) {
14150 xmlSchemaVCustomErr(ctxt,
14151 XML_SCHEMAV_INTERNAL,
14152 (xmlNodePtr) attr, NULL,
14153 "Internal error: xmlSchemaValidateElementByDeclaration, "
14154 "validating the attribute 'xsi:nil'", NULL);
14155 if (attrValue != NULL)
14156 xmlFree(attrValue);
14157 return (-1);
14158 }
14159 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
14160 /*
14161 * cvc-elt (3.3.4) : 3.1
14162 */
14163 xmlSchemaVCustomErr(ctxt,
14164 XML_SCHEMAV_CVC_ELT_3_1,
14165 elem, NULL,
14166 "The element is not 'nillable'", NULL);
14167 } else {
14168 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
14169 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
14170 nilled = 1;
14171 ret = 0;
14172 /*
14173 * cvc-elt (3.3.4) : 3.2.1
14174 */
14175 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
14176 xmlSchemaVCustomErr(ctxt,
14177 XML_SCHEMAV_CVC_ELT_3_2_1,
14178 /* XML_SCHEMAS_ERR_NOTEMPTY, */
14179 elem, NULL,
14180 "The 'nilled' element must have no character or element "
14181 "content", NULL);
14182 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
14183 }
14184 /*
14185 * cvc-elt (3.3.4) : 3.2.2
14186 */
14187 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
14188 (elemDecl->value != NULL)) {
14189 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
14190 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
14191 elem, NULL,
14192 "There is a fixed value constraint defined for "
14193 "the 'nilled' element", NULL);
14194 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
14195 }
14196
14197 }
14198 }
14199 if (attrValue != NULL)
14200 xmlFree(attrValue);
14201 }
14202
14203 /*
14204 * cvc-elt (3.3.4) : 4
14205 * Handle 'xsi:type'.
14206 */
14207 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
14208 if (attr != NULL) {
14209 xmlChar *nsName = NULL, *local = NULL;
14210
14211 /*
14212 * TODO: We should report a *warning* that the type was overriden
14213 * by the instance.
14214 */
14215
14216 /*
14217 * cvc-elt (3.3.4) : 4.1
14218 */
14219 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
14220 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
14221 &nsName, &local);
14222 if (ret < 0) {
14223 xmlSchemaVCustomErr(ctxt,
14224 XML_SCHEMAV_INTERNAL,
14225 (xmlNodePtr) attr, NULL,
14226 "Internal error: xmlSchemaValidateElementByDeclaration, "
14227 "validating the attribute 'xsi:type'", NULL);;
14228 FREE_AND_NULL(attrValue)
14229 FREE_AND_NULL(nsName)
14230 FREE_AND_NULL(local)
14231 return (-1);
14232 } else if (ret == 1) {
14233 xmlSchemaVSimpleTypeErr(ctxt,
14234 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
14235 (xmlNodePtr) attr, attrValue,
14236 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
14237 } else if (ret == 2) {
14238 xmlSchemaVCustomErr(ctxt,
14239 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
14240 (xmlNodePtr) attr,
14241 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
14242 "The QName value '%s' has no "
14243 "corresponding namespace declaration in scope",
14244 attrValue);
14245 } else {
14246 /*
14247 * cvc-elt (3.3.4) : 4.2
14248 */
14249 type = xmlSchemaGetType(ctxt->schema, local, nsName);
14250 if (type == NULL) {
14251 xmlChar *strA = NULL;
14252
14253 xmlSchemaVCustomErr(ctxt,
14254 XML_SCHEMAV_CVC_ELT_4_2,
14255 (xmlNodePtr) attr,
14256 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
14257 "The value %s does not resolve to a type "
14258 "definition",
14259 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
14260 FREE_AND_NULL(strA);
14261 } else {
14262 TODO
14263 /*
14264 * TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
14265 */
14266 }
14267 }
14268 FREE_AND_NULL(attrValue)
14269 FREE_AND_NULL(nsName)
14270 FREE_AND_NULL(local)
14271 } else {
14272 type = elemDecl->subtypes;
14273 /* TODO: Change the handling of missing types according to
14274 * the spec.
14275 */
14276 if (type == NULL) {
14277 xmlSchemaVCustomErr(ctxt,
14278 XML_SCHEMAV_INTERNAL,
14279 /* XML_SCHEMAS_ERR_NOTYPE */
14280 elem, NULL,
14281 "The element declaration has no type assigned", NULL);
14282 return (-1);
14283 }
14284 }
14285
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014286 /*
14287 * TODO: Since this should be already checked by the content model automaton,
14288 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
14289 * has been changed to XML_SCHEMAV_INTERNAL.
14290 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014291 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014292 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014293 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014294 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014295 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014296 "Element %s: missing child %s\n",
14297 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014298 }
14299 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014300 }
14301 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014302 /*
14303 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014304 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014305 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014306 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014307 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014308 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014309 "Element %s: missing child %s found %s\n",
14310 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014311 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014312 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014313 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014314 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014315 * URGENT TODO: Look up what to do if the type is not available.
14316 */
14317 if (type != NULL)
14318 xmlSchemaValidateElementByType(ctxt, type);
14319
14320 ctxt->node = elem;
14321 ctxt->type = (xmlSchemaTypePtr) elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014322 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014323}
14324
Daniel Veillard4255d502002-04-16 15:50:10 +000014325/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014326 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000014327 * @ctxt: a schema validation context
14328 * @node: the top node.
14329 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014330 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
14331 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014332 *
14333 * Returns 0 if the element is valid, a positive error code
14334 * number otherwise and -1 in case of an internal error.
14335 */
14336static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014337xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
14338 xmlSchemaWildcardPtr wild,
14339 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014340{
14341 const xmlChar *uri;
14342 int ret = 0;
14343 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014344
14345 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
14346 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14347 if (ret == -1) {
14348 xmlSchemaVCustomErr(ctxt,
14349 XML_SCHEMAV_INTERNAL,
14350 ctxt->node, NULL,
14351 "Internal error: xmlSchemaValidateElement, "
14352 "assembling schema by xsi", NULL);
14353 return (-1);
14354 }
14355 /*
14356 * NOTE: We won't react on schema parser errors here.
14357 * TODO: But a warning would be nice.
14358 */
14359 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014360 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
14361 xmlSchemaElementPtr decl = NULL;
14362
14363 if (node->ns != NULL)
14364 decl = xmlHashLookup3(ctxt->schema->elemDecl,
14365 node->name, node->ns->href, NULL);
14366 else
14367 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
14368 if (decl != NULL) {
14369 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014370 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014371 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014372 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014373 "Internal error: xmlSchemaValidateAnyInternal, "
14374 "validating an element in the context of a wildcard.",
14375 NULL, NULL);
14376 } else if (ret > 0)
14377 return (ret);
14378 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
14379 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014380 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014381 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000014382 return (ctxt->err);
14383 }
14384 }
14385 if (node->children != NULL) {
14386 child = node->children;
14387 do {
14388 if (child->type == XML_ELEMENT_NODE) {
14389 if (child->ns != NULL)
14390 uri = child->ns->href;
14391 else
14392 uri = NULL;
14393 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014394 /* TODO: error code. */
14395 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014396 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014397 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000014398 return (ctxt->err);
14399 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014400 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
14401 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014402 if (ret != 0)
14403 return (ret);
14404 }
14405 child = child->next;
14406 } while (child != NULL);
14407 }
14408 return (0);
14409}
14410
14411/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014412 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000014413 * @ctxt: a schema validation context
14414 *
14415 * Returns 0 if the element is valid, a positive error code
14416 * number otherwise and -1 in case of an internal or API error.
14417 */
14418static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014419xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
14420 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014421{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014422 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
14423 (ctxt->node == NULL)) {
14424 xmlSchemaVCustomErr(ctxt,
14425 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
14426 "Internal error: xmlSchemaValidateElementByWildcard, "
14427 "bad arguments", NULL);
14428 return (-1);
14429 }
14430 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
14431 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014432}
14433
14434/**
William M. Brack2f2a6632004-08-20 23:09:47 +000014435 * xmlSchemaValidateAnyTypeContent:
14436 * @ctxt: a schema validation context
14437 * @node: the current element
14438 *
14439 * This one validates the content of an element of the type
14440 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
14441 * thus elements in the subtree will be validated, if a corresponding
14442 * declaration in the schema exists.
14443 *
14444 * Returns 0 if the element and its subtree is valid, a positive error code
14445 * otherwise and -1 in case of an internal or API error.
14446 */
14447static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014448xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
14449 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014450{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014451 xmlSchemaTypePtr oldtype;
14452 xmlNodePtr top, cur;
14453 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000014454 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014455
14456 if ((type == NULL) || (ctxt->node == NULL))
14457 return (-1);
14458
14459 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000014460 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014461
14462 oldtype = ctxt->type;
14463 top = ctxt->node;
14464 /*
14465 * STREAM: Child nodes are processed.
14466 */
14467 cur = ctxt->node->children;
14468 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014469 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014470 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014471 /*
14472 * The process contents of the wildcard is "lax", thus
14473 * we need to validate the element if a declaration
14474 * exists.
14475 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014476 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000014477 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014478 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014479 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014480 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014481 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014482 ctxt->node = cur;
14483 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
14484 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000014485 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014486 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014487 "Internal error: xmlSchemaValidateAnyTypeContent, "
14488 "validating an element in the context of a wildcard.",
14489 NULL, NULL);
14490 return (ret);
14491 } else if (ret > 0)
14492 return (ret);
14493 skipContent = 1;
14494 }
14495 }
14496 /*
14497 * Browse the full subtree, deep first.
14498 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014499 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014500 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014501 cur = cur->children;
14502 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014503 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014504 cur = cur->next;
14505 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014506 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014507 while (cur != top) {
14508 if (cur->parent != NULL)
14509 cur = cur->parent;
14510 if ((cur != top) && (cur->next != NULL)) {
14511 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000014512 break;
14513 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014514 if (cur->parent == NULL) {
14515 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000014516 break;
14517 }
14518 }
14519 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014520 if (cur == top)
14521 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000014522 } else
14523 break;
14524 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014525 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000014526 return (0);
14527}
14528
14529/**
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014530 * xmlSchemaHasElemOrCharContent:
14531 * @node: the node
14532 *
14533 * Scours the content of the given node for element
14534 * and character nodes.
14535 *
14536 * Returns 1 if an element or character node is found,
14537 * 0 otherwise.
14538 */
14539static int
14540xmlSchemaHasElemOrCharContent(xmlNodePtr node)
14541{
14542 xmlNodePtr cur;
14543
14544 if (node == NULL)
14545 return (0);
14546 cur = node->children;
14547 while (cur != NULL) {
14548 if ((cur->type == XML_ELEMENT_NODE) ||
14549 /*
14550 * TODO: Ask Daniel if these are all character nodes.
14551 */
14552 (cur->type == XML_TEXT_NODE) ||
14553 (cur->type == XML_CDATA_SECTION_NODE) ||
14554 /*
14555 * TODO: How XML_ENTITY_NODEs evaluated?
14556 */
14557 (cur->type == XML_ENTITY_REF_NODE) ||
14558 (cur->type == XML_ENTITY_NODE)) {
14559 return (1);
14560 }
14561 cur = cur->next;
14562 }
14563 return (0);
14564}
14565
14566/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014567 * xmlSchemaValidateComplexType:
14568 * @ctxt: a schema validation context
14569 * @node: the top node.
14570 *
14571 * Validate the content of an element expected to be a complex type type
14572 * xmlschema-1.html#cvc-complex-type
14573 * Validation Rule: Element Locally Valid (Complex Type)
14574 *
14575 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000014576 * number otherwise and -1 in case of internal or API error.
14577 * Note on reported errors: Although it might be nice to report
14578 * the name of the simple/complex type, used to validate the content
14579 * of a node, it is quite unnecessary: for global defined types
14580 * the local name of the element is equal to the NCName of the type,
14581 * for local defined types it makes no sense to output the internal
14582 * computed name of the type. TODO: Instead, one should attach the
14583 * struct of the type involved to the error handler - this allows
14584 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000014585 */
14586static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014587xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
14588 xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014589{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014590 xmlSchemaTypePtr oldtype;
14591 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014592 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000014593 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014594 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014596 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
14597 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014598
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014599 oldtype = ctxt->type;
14600 ctxt->type = type;
14601 elem = ctxt->node;
14602
14603
14604 /*
14605 * Verify the attributes
14606 */
14607 /*
14608 * TODO: This "attrTop" thing is not needed any more.
14609 */
14610 attrs = ctxt->attr;
14611 attrTop = ctxt->attrTop;
14612 /*
14613 * STREAM: Attribute nodes are processed.
14614 */
14615 xmlSchemaRegisterAttributes(ctxt, elem->properties);
14616 xmlSchemaValidateAttributes(ctxt, elem, type);
14617 if (ctxt->attr != NULL)
14618 xmlSchemaFreeAttributeStates(ctxt->attr);
14619 ctxt->attr = attrs;
14620 ctxt->attrTop = attrTop;
14621
14622 /*
14623 * FIXME TODO: This one creates a regexp even if no content
14624 * model was defined. Somehow ->contModel is always not NULL
14625 * for complex types, even if they are empty.
14626 */
14627 /*
14628 * FIXME TODO URGENT: Move the content model to the
14629 * type definition.
14630 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014631 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014632 case XML_SCHEMA_CONTENT_EMPTY: {
14633 /*
14634 * 1 If the {content type} is empty, then the element information
14635 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000014636 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014637 /*
14638 * TODO: Is the entity stuff correct?
14639 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014640 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014641 xmlSchemaVComplexTypeErr(ctxt,
14642 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014643 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014644 "Character or element content is not allowed, "
14645 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014646 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014647 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014648 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014649 case XML_SCHEMA_CONTENT_MIXED:
14650 if ((type->subtypes == NULL) &&
14651 (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))) {
14652 /*
14653 * The type has 'anyType' as its base and no content model
14654 * is defined -> use 'anyType' as the type to validate
14655 * against.
14656 */
14657 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
14658 /* TODO: Handle -1. */
14659 break;
14660 }
14661 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014662 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014663 {
14664 xmlRegExecCtxtPtr oldregexp = NULL;
14665
14666
14667 /*
14668 * Content model check initialization.
14669 */
14670 if (type->contModel != NULL) {
14671 oldregexp = ctxt->regexp;
14672 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
14673 (xmlRegExecCallbacks)
14674 xmlSchemaValidateCallback, ctxt);
14675#ifdef DEBUG_AUTOMATA
14676 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
14677#endif
14678 }
14679 /* xmlSchemaValidateElementByType(ctxt, elemDecl->subtypes); */
14680
14681
14682 /*
14683 * STREAM: Children are processed.
14684 */
14685 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014686 while (child != NULL) {
14687 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014688 if (child->ns != NULL)
14689 nsUri = child->ns->href;
14690 else
14691 nsUri = NULL;
14692 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014693 child->name, nsUri, child);
14694 /*
14695 * URGENT TODO: Could we anchor an error report
14696 * here to notify of invalid elements?
14697 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014698#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000014699 if (ret < 0)
14700 xmlGenericError(xmlGenericErrorContext,
14701 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000014702 else
14703 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014704 " --> %s\n", child->name);
14705#endif
14706 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
14707 /*
14708 * TODO: Ask Daniel if this are all character nodes.
14709 */
14710 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
14711 (child->type == XML_ENTITY_NODE) ||
14712 (child->type == XML_ENTITY_REF_NODE) ||
14713 (child->type == XML_CDATA_SECTION_NODE))) {
14714 /*
14715 * 2.3 If the {content type} is element-only, then the
14716 * element information item has no character information
14717 * item [children] other than those whose [character
14718 * code] is defined as a white space in [XML 1.0 (Second
14719 * Edition)].
14720 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014721 xmlSchemaVComplexTypeErr(ctxt,
14722 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014723 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014724 "Character content is not allowed, "
14725 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014726 break;
14727 }
14728 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014729 }
14730 /*
14731 * Content model check finalization.
14732 */
14733 if (type->contModel != NULL) {
14734 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
14735#ifdef DEBUG_AUTOMATA
14736 xmlGenericError(xmlGenericErrorContext,
14737 "====> %s : %d\n", elem->name, ret);
14738#endif
14739 if (ret == 0) {
14740 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14741 elem, type, "The element content is not valid", NULL);
14742 } else if (ret < 0) {
14743 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14744 elem, type, "The element content is not valid", NULL);
14745#ifdef DEBUG_CONTENT
14746 } else {
14747 xmlGenericError(xmlGenericErrorContext,
14748 "Element %s content check succeeded\n",
14749 elem->name);
14750
14751#endif
14752 }
14753 xmlRegFreeExecCtxt(ctxt->regexp);
14754 ctxt->regexp = oldregexp;
14755 }
14756 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014757 break;
14758 case XML_SCHEMA_CONTENT_SIMPLE:
14759 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014760 xmlChar *value = NULL;
14761 /*
14762 * We hit a complexType with a simpleContent resolving
14763 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000014764 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014765 /*
14766 * 2.2 If the {content type} is a simple type definition,
14767 * then the element information item has no element
14768 * information item [children], and the ·normalized value·
14769 * of the element information item is ·valid· with respect
14770 * to that simple type definition as defined by String
14771 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014772 */
14773 /*
14774 * STREAM: Children are processed.
14775 */
14776 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014777 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014778 /*
14779 * TODO: Could the entity stuff produce elements
14780 * as well?
14781 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014782 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014783 xmlSchemaVComplexTypeErr(ctxt,
14784 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014785 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014786 "Element content is not allowed, because "
14787 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014788 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14789 break;
14790 }
14791 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014792 }
14793 ctxt->node = elem;
14794 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014795 if (ret == 0) {
14796 /*
14797 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014798 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014799 /*
14800 * STREAM: Children are processed.
14801 */
14802 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014803 value = NULL;
14804 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014805 value = xmlNodeGetContent(elem);
14806 /*
14807 * URGENT TODO: Should facets for the simple type validation be
14808 * disabled, if the derivation of facets for complex types
14809 * is implemented?
14810 */
14811 /*
14812 * NOTE: This call won't check the correct types of the
14813 * content nodes, since this should be done here.
14814 */
14815 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014816 if (ret > 0) {
14817 /*
14818 * NOTE: Although an error will be reported by
14819 * xmlSchemaValidateSimpleTypeValue, the spec wants
14820 * a specific complex type error to be reported
14821 * additionally.
14822 */
14823 xmlSchemaVComplexTypeErr(ctxt,
14824 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014825 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014826 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014827 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14828 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014829 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014830 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014831 "Element '%s': Error while validating character "
14832 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014833 elem->name, type->name);
14834 if (value != NULL)
14835 xmlFree(value);
14836 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014837 return (-1);
14838 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014839 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014840 if (ret == 0) {
14841 /*
14842 * Apply facets of the complexType. Be sure to pass the
14843 * built-in type to xmlSchemaValidateFacetsInternal.
14844 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014845 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014846 * are used, or if the facets, defined by this complex type,
14847 * are to be used only. This here applies both facet sets.
14848 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014849
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014850 ret = xmlSchemaValidateFacetsInternal(ctxt,
14851 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014852 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014853 xmlSchemaVComplexTypeErr(ctxt,
14854 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014855 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014856 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014857 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14858 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014859 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014860 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014861 "Element '%s': Error while validating character "
14862 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014863 "apply facets.\n",
14864 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014865 if (value != NULL)
14866 xmlFree(value);
14867 ctxt->type = oldtype;
14868 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014869 }
14870 }
14871 if (value != NULL)
14872 xmlFree(value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014873 break;
14874 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014875 default:
14876 TODO xmlGenericError(xmlGenericErrorContext,
14877 "unimplemented content type %d\n",
14878 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000014879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014880 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014881 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014882}
14883
14884/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014885 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000014886 * @ctxt: a schema validation context
14887 * @elem: an element
14888 * @type: the list of type declarations
14889 *
14890 * Validate the content of an element against the types.
14891 *
14892 * Returns 0 if the element is schemas valid, a positive error code
14893 * number otherwise and -1 in case of internal or API error.
14894 */
14895static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014896xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
14897 xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014898{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014899 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000014900
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014901 /*
14902 * This one is called by "xmlSchemaValidateElementByDeclaration".
14903 * It will forward to the proper validation
14904 * procedures for the given type.
14905 */
14906 if ((type == NULL) || (ctxt == NULL))
14907 return (-1);
14908
Daniel Veillard4255d502002-04-16 15:50:10 +000014909 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014910 * @elemDecl->subtypes will be of type XML_SCHEMA_TYPE_COMPLEX,
14911 * XML_SCHEMA_TYPE_SIMPLE or XML_SCHEMA_TYPE_BASIC.
14912 */
14913 switch (type->type) {
14914 case XML_SCHEMA_TYPE_COMPLEX:
14915 ret = xmlSchemaValidateElementByComplexType(ctxt, type);
14916 break;
14917 case XML_SCHEMA_TYPE_SIMPLE:
14918 ret = xmlSchemaValidateElementBySimpleType(ctxt, type);
14919 break;
14920 case XML_SCHEMA_TYPE_BASIC:
14921 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
14922 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
14923 else
14924 ret = xmlSchemaValidateElementBySimpleType(ctxt, type);
14925 break;
14926 default:
14927 ret = -1;
14928 break;
14929 }
14930 if (ret == -1)
14931 return (-1);
14932 else
14933 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014934}
14935
14936
14937/**
14938 * xmlSchemaValidateAttributes:
14939 * @ctxt: a schema validation context
14940 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000014941 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000014942 *
14943 * Validate the attributes of an element.
14944 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000014945 * 1. Existent, invalid attributes are reported in the form
14946 * "prefix:localName".
14947 * Reason: readability - it is easier to find the actual XML
14948 * representation of the attributes QName.
14949 * 2. Missing attributes are reported in the form
14950 * {"URI", "localName"}.
14951 * This is necessary, since the the prefix need not to be declared
14952 * at all, and thus is not computable.
14953 *
Daniel Veillard4255d502002-04-16 15:50:10 +000014954 * Returns 0 if the element is schemas valid, a positive error code
14955 * number otherwise and -1 in case of internal or API error.
14956 */
14957static int
Daniel Veillard3646d642004-06-02 19:19:14 +000014958xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014959{
Daniel Veillard3646d642004-06-02 19:19:14 +000014960 int ret;
14961 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000014962 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014963 const xmlChar *nsURI;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014964 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014965 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000014966 int found;
William M. Brack803812b2004-06-03 02:11:24 +000014967 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014968 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000014969#ifdef DEBUG_ATTR_VALIDATION
14970 int redundant = 0;
14971#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014972
Daniel Veillardc0826a72004-08-10 14:17:33 +000014973 /*
14974 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
14975 * if we have an attribute reference or an attribute declaration.
14976 */
14977 /*
14978 * Allow all attributes if the type is anyType.
14979 */
14980 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
14981 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014982
14983 oldnode = ctxt->node;
14984 if (type != NULL)
14985 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000014986 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000014987 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000014988 attrDecl = attrUse->attr;
14989#ifdef DEBUG_ATTR_VALIDATION
14990 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
14991 printf("attr use - use: %d\n", attrDecl->occurs);
14992#endif
14993 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
14994
14995 if (curState->decl == attrUse->attr) {
14996#ifdef DEBUG_ATTR_VALIDATION
14997 redundant = 1;
14998#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014999 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015000 attr = curState->attr;
15001#ifdef DEBUG_ATTR_VALIDATION
15002 printf("attr - name: %s\n", attr->name);
15003 if (attr->ns != NULL)
15004 printf("attr - ns: %s\n", attr->ns->href);
15005 else
15006 printf("attr - ns: none\n");
15007#endif
15008 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015009 if (attr == NULL)
15010 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015011 if (attrDecl->ref != NULL) {
15012 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015013 continue;
15014 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000015015 if ((attrDecl->refNs == NULL) ||
15016 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015017 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015018 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015019 continue;
15020 }
15021 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000015022 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015023 continue;
15024 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015025 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015026 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015027 if (attr->ns == NULL) {
15028 /*
William M. Bracke7091952004-05-11 15:09:58 +000015029 * accept an unqualified attribute only if the target
15030 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015031 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015032 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000015033 /*
15034 * This check was removed, since the target namespace
15035 * was evaluated during parsing and already took
15036 * "attributeFormDefault" into account.
15037 */
15038 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015039 continue;
15040 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000015041 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015042 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015043 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015044 attr->ns->href))
15045 continue;
15046 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015047 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015048#ifdef DEBUG_ATTR_VALIDATION
15049 printf("found\n");
15050#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000015051 found = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015052
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000015053
Daniel Veillard3646d642004-06-02 19:19:14 +000015054 if (attrDecl->subtypes == NULL) {
15055 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
15056 curState->decl = attrDecl;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015057 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000015058 "Internal error: attribute %s type not resolved\n",
15059 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015060 continue;
15061 }
15062 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015063 ctxt->node = (xmlNodePtr) attr;
15064 ctxt->cur = attr->children;
15065 /*
15066 * NOTE: This call also checks the content nodes for correct type.
15067 */
15068 ret = xmlSchemaValidateSimpleTypeValue(ctxt, attrDecl->subtypes,
15069 value, 1, 1, 1, 1);
Daniel Veillard3646d642004-06-02 19:19:14 +000015070 if (ret != 0)
15071 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
15072 else
15073 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15074 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015075 if (value != NULL) {
15076 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000015077 }
15078 }
15079 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
15080 xmlSchemaAttrStatePtr tmp;
15081
15082#ifdef DEBUG_ATTR_VALIDATION
15083 printf("required attr not found\n");
15084#endif
15085 /*
15086 * Add a new dummy attribute state.
15087 */
15088 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
15089 if (tmp == NULL) {
15090 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015091 ctxt->node = oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000015092 return (-1);
15093 }
15094 tmp->attr = NULL;
15095 tmp->state = XML_SCHEMAS_ATTR_MISSING;
15096 tmp->decl = attrDecl;
15097 tmp->next = NULL;
15098
15099 if (reqAttrStates == NULL) {
15100 reqAttrStates = tmp;
15101 reqAttrStatesTop = tmp;
15102 } else {
15103 reqAttrStatesTop->next = tmp;
15104 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015105 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015106
15107 }
15108 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015109 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015110 /*
15111 * Add required attributes to the attribute states of the context.
15112 */
15113 if (reqAttrStates != NULL) {
15114 if (ctxt->attr == NULL) {
15115 ctxt->attr = reqAttrStates;
15116 } else {
15117 ctxt->attrTop->next = reqAttrStates;
15118 }
15119 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015120 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015121 /*
15122 * Process wildcards.
15123 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015124 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000015125#ifdef DEBUG_ATTR_VALIDATION
15126 xmlSchemaWildcardNsPtr ns;
15127 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015128 if (type->attributeWildcard->processContents ==
15129 XML_SCHEMAS_ANY_LAX)
15130 printf("processContents: lax\n");
15131 else if (type->attributeWildcard->processContents ==
15132 XML_SCHEMAS_ANY_STRICT)
15133 printf("processContents: strict\n");
15134 else
15135 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000015136 if (type->attributeWildcard->any)
15137 printf("type: any\n");
15138 else if (type->attributeWildcard->negNsSet != NULL) {
15139 printf("type: negated\n");
15140 if (type->attributeWildcard->negNsSet->value == NULL)
15141 printf("ns: (absent)\n");
15142 else
15143 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
15144 } else if (type->attributeWildcard->nsSet != NULL) {
15145 printf("type: set\n");
15146 ns = type->attributeWildcard->nsSet;
15147 while (ns != NULL) {
15148 if (ns->value == NULL)
15149 printf("ns: (absent)\n");
15150 else
15151 printf("ns: %s\n", ns->value);
15152 ns = ns->next;
15153 }
15154 } else
15155 printf("empty\n");
15156
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015157
15158#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000015159 curState = ctxt->attr;
15160 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015161 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
15162 if (curState->attr->ns != NULL)
15163 nsURI = curState->attr->ns->href;
15164 else
15165 nsURI = NULL;
15166 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
15167 nsURI)) {
15168 /*
15169 * Handle processContents.
15170 */
15171 if ((type->attributeWildcard->processContents ==
15172 XML_SCHEMAS_ANY_LAX) ||
15173 (type->attributeWildcard->processContents ==
15174 XML_SCHEMAS_ANY_STRICT)) {
15175
15176 attr = curState->attr;
15177 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
15178 attr->name, nsURI);
15179 if (attrDecl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015180 value = xmlNodeListGetString(elem->doc,
15181 attr->children, 1);
15182 ctxt->node = (xmlNodePtr) attr;
15183 ctxt->cur = attr->children;
15184 /*
15185 * NOTE: This call also checks the content nodes
15186 * for correct type.
15187 */
15188 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15189 attrDecl->subtypes, value, 1, 1, 1, 1);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015190 if (ret != 0)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015191 curState->state =
15192 XML_SCHEMAS_ATTR_INVALID_VALUE;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015193 else
15194 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15195 curState->decl = attrDecl;
15196 if (value != NULL) {
15197 xmlFree(value);
15198 }
15199
15200 } else if (type->attributeWildcard->processContents ==
15201 XML_SCHEMAS_ANY_LAX) {
15202 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15203 }
15204 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000015205 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015206 }
15207 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015208 curState = curState->next;
15209 }
15210 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015211
Daniel Veillardc0826a72004-08-10 14:17:33 +000015212 /*
15213 * Report missing and illegal attributes.
15214 */
15215 if (ctxt->attr != NULL) {
15216 curState = ctxt->attr;
15217 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
15218 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
15219 attr = curState->attr;
15220 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
15221 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015222 else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
15223 /* TODO: "prohibited" won't ever be touched here!.
15224 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
15225 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015226 /*
15227 * TODO: One might report different error messages
15228 * for the following errors.
15229 */
15230 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015231 xmlSchemaVIllegalAttrErr(ctxt,
15232 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
15233 } else {
15234 xmlSchemaVIllegalAttrErr(ctxt,
15235 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
15236 }
15237 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015238 }
15239 curState = curState->next;
15240 }
15241 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015242#ifdef DEBUG_ATTR_VALIDATION
15243 if (redundant)
15244 xmlGenericError(xmlGenericErrorContext,
15245 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
15246 type->name);
15247#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015248 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015249 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015250}
15251
15252/**
15253 * xmlSchemaValidateElement:
15254 * @ctxt: a schema validation context
15255 * @elem: an element
15256 *
15257 * Validate an element in a tree
15258 *
15259 * Returns 0 if the element is schemas valid, a positive error code
15260 * number otherwise and -1 in case of internal or API error.
15261 */
15262static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015263xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015264{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015265 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000015266 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000015267
Daniel Veillardc0826a72004-08-10 14:17:33 +000015268 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015269 * This one is called by xmlSchemaValidateDocument and
15270 * xmlSchemaValidateOneElement.
15271 */
15272 /*
15273 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015274 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015275 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
15276 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15277 if (ret == -1) {
15278 xmlSchemaVCustomErr(ctxt,
15279 XML_SCHEMAV_INTERNAL,
15280 ctxt->node, NULL,
15281 "Internal error: xmlSchemaValidateElement, "
15282 "assembling schema by xsi", NULL);
15283 return (-1);
15284 }
15285 /*
15286 * NOTE: We won't react on schema parser errors here.
15287 * TODO: But a warning would be nice.
15288 */
15289 }
15290
15291 if (ctxt->node->ns != NULL)
15292 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, ctxt->node->ns->href);
15293 else
15294 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
15295
Daniel Veillard4255d502002-04-16 15:50:10 +000015296 if (elemDecl == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015297 xmlSchemaVCustomErr(ctxt,
15298 XML_SCHEMAV_CVC_ELT_1,
15299 ctxt->node, NULL,
15300 "No matching global declaration available", NULL);
15301 return (XML_SCHEMAV_CVC_ELT_1);
15302 }
15303
15304 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
15305 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015306 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015307 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15308 "Internal error: xmlSchemaValidateElement, "
15309 "calling validation by declaration", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015310 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015311 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000015312}
15313
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015314
Daniel Veillard4255d502002-04-16 15:50:10 +000015315/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015316 * xmlSchemaValidateOneElement:
15317 * @ctxt: a schema validation context
15318 * @elem: an element node
15319 *
15320 * Validate a branch of a tree, starting with the given @elem.
15321 *
15322 * Returns 0 if the element and its subtree is valid, a positive error
15323 * code number otherwise and -1 in case of an internal or API error.
15324 */
15325int
15326xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
15327{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015328 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015329 return (-1);
15330
15331 ctxt->doc = elem->doc;
15332 ctxt->err = 0;
15333 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015334 ctxt->node = elem;
15335 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015336}
15337
15338/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015339 * xmlSchemaValidateDocument:
15340 * @ctxt: a schema validation context
15341 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015342 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000015343 *
15344 * Validate a document tree in memory.
15345 *
15346 * Returns 0 if the document is schemas valid, a positive error code
15347 * number otherwise and -1 in case of internal or API error.
15348 */
15349static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015350xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
15351{
Daniel Veillard4255d502002-04-16 15:50:10 +000015352 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015353
Daniel Veillard4255d502002-04-16 15:50:10 +000015354 root = xmlDocGetRootElement(doc);
15355 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015356 xmlSchemaVCustomErr(ctxt,
15357 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
15358 (xmlNodePtr) doc, NULL,
15359 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015360 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015361 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015362 /*
15363 * Okay, start the recursive validation
15364 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015365 ctxt->node = root;
15366 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015367
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015368 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015369}
15370
15371/************************************************************************
15372 * *
15373 * SAX Validation code *
15374 * *
15375 ************************************************************************/
15376
15377/************************************************************************
15378 * *
15379 * Validation interfaces *
15380 * *
15381 ************************************************************************/
15382
15383/**
15384 * xmlSchemaNewValidCtxt:
15385 * @schema: a precompiled XML Schemas
15386 *
15387 * Create an XML Schemas validation context based on the given schema
15388 *
15389 * Returns the validation context or NULL in case of error
15390 */
15391xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015392xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
15393{
Daniel Veillard4255d502002-04-16 15:50:10 +000015394 xmlSchemaValidCtxtPtr ret;
15395
15396 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
15397 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015398 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015399 return (NULL);
15400 }
15401 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015402 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000015403 ret->attrTop = NULL;
15404 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015405 return (ret);
15406}
15407
15408/**
15409 * xmlSchemaFreeValidCtxt:
15410 * @ctxt: the schema validation context
15411 *
15412 * Free the resources associated to the schema validation context
15413 */
15414void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015415xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
15416{
Daniel Veillard4255d502002-04-16 15:50:10 +000015417 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015418 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015419 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000015420 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000015421 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015422 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000015423 xmlFree(ctxt);
15424}
15425
15426/**
15427 * xmlSchemaSetValidErrors:
15428 * @ctxt: a schema validation context
15429 * @err: the error function
15430 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000015431 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000015432 *
William M. Brack2f2a6632004-08-20 23:09:47 +000015433 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000015434 */
15435void
15436xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015437 xmlSchemaValidityErrorFunc err,
15438 xmlSchemaValidityWarningFunc warn, void *ctx)
15439{
Daniel Veillard4255d502002-04-16 15:50:10 +000015440 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015441 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015442 ctxt->error = err;
15443 ctxt->warning = warn;
15444 ctxt->userData = ctx;
15445}
15446
15447/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015448 * xmlSchemaGetValidErrors:
15449 * @ctxt: a XML-Schema validation context
15450 * @err: the error function result
15451 * @warn: the warning function result
15452 * @ctx: the functions context result
15453 *
15454 * Get the error and warning callback informations
15455 *
15456 * Returns -1 in case of error and 0 otherwise
15457 */
15458int
15459xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
15460 xmlSchemaValidityErrorFunc * err,
15461 xmlSchemaValidityWarningFunc * warn, void **ctx)
15462{
15463 if (ctxt == NULL)
15464 return (-1);
15465 if (err != NULL)
15466 *err = ctxt->error;
15467 if (warn != NULL)
15468 *warn = ctxt->warning;
15469 if (ctx != NULL)
15470 *ctx = ctxt->userData;
15471 return (0);
15472}
15473
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015474#if 0 /* Will be enabled if it is clear what options are needed. */
15475/**
15476 * xmlSchemaValidCtxtSetOptions:
15477 * @ctxt: a schema validation context
15478 * @options: a combination of xmlSchemaValidOption
15479 *
15480 * Sets the options to be used during the validation.
15481 *
15482 * Returns 0 in case of success, -1 in case of an
15483 * API error.
15484 */
15485static int
15486xmlSchemaValidCtxtSetOptions(xmlSchemaValidCtxtPtr ctxt,
15487 int options)
15488
15489{
15490 int i;
15491
15492 if (ctxt == NULL)
15493 return (-1);
15494 /*
15495 * WARNING: Change the start value if adding to the
15496 * xmlSchemaValidOption.
15497 */
15498 for (i = 1; i <= (int) sizeof(int) * 8; i++) {
15499 if (options & 1<<i) {
15500 return (-1);
15501 }
15502 }
15503 ctxt->options = options;
15504 return (0);
15505}
15506
15507/**
15508 * xmlSchemaValidCtxtGetOptions:
15509 * @ctxt: a schema validation context
15510 *
15511 * Returns the option combination of the validation context.
15512 */
15513static int
15514xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
15515
15516{
15517 if (ctxt == NULL)
15518 return (-1);
15519 else
15520 return (ctxt->options);
15521}
15522#endif
15523
Daniel Veillard259f0df2004-08-18 09:13:18 +000015524/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015525 * xmlSchemaValidateDoc:
15526 * @ctxt: a schema validation context
15527 * @doc: a parsed document tree
15528 *
15529 * Validate a document tree in memory.
15530 *
15531 * Returns 0 if the document is schemas valid, a positive error code
15532 * number otherwise and -1 in case of internal or API error.
15533 */
15534int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015535xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
15536{
Daniel Veillard4255d502002-04-16 15:50:10 +000015537 int ret;
15538
15539 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015540 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015541
15542 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000015543 ctxt->err = 0;
15544 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015545
Daniel Veillard4255d502002-04-16 15:50:10 +000015546 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015547 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000015548}
15549
15550/**
15551 * xmlSchemaValidateStream:
15552 * @ctxt: a schema validation context
15553 * @input: the input to use for reading the data
15554 * @enc: an optional encoding information
15555 * @sax: a SAX handler for the resulting events
15556 * @user_data: the context to provide to the SAX handler.
15557 *
15558 * Validate a document tree in memory.
15559 *
15560 * Returns 0 if the document is schemas valid, a positive error code
15561 * number otherwise and -1 in case of internal or API error.
15562 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015563int
Daniel Veillard4255d502002-04-16 15:50:10 +000015564xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015565 xmlParserInputBufferPtr input, xmlCharEncoding enc,
15566 xmlSAXHandlerPtr sax, void *user_data)
15567{
Daniel Veillard4255d502002-04-16 15:50:10 +000015568 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015569 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015570 ctxt->input = input;
15571 ctxt->enc = enc;
15572 ctxt->sax = sax;
15573 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015574 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015575}
15576
15577#endif /* LIBXML_SCHEMAS_ENABLED */