blob: 000a0ddf1e850fbb2f33ff0b64722b289df8418e [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 Veillard75bb3bb2003-05-12 15:25:56 +000012537 int nberrors;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012538 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012539
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012540 /*
12541 * This one is used if the schema to be parsed was specified via
12542 * the API; i.e. not automatically by the validated instance document.
12543 */
12544
Daniel Veillard4255d502002-04-16 15:50:10 +000012545 xmlSchemaInitTypes();
12546
Daniel Veillard6045c902002-10-09 21:13:59 +000012547 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000012548 return (NULL);
12549
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012550 nberrors = ctxt->nberrors;
12551 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000012552 ctxt->counter = 0;
12553 ctxt->container = NULL;
12554
12555 /*
12556 * First step is to parse the input document into an DOM/Infoset
12557 */
Daniel Veillard6045c902002-10-09 21:13:59 +000012558 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012559 doc = xmlReadFile((const char *) ctxt->URL, NULL,
12560 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012561 if (doc == NULL) {
12562 xmlSchemaPErr(ctxt, NULL,
12563 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012564 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012565 ctxt->URL, NULL);
12566 return (NULL);
12567 }
Daniel Veillard6045c902002-10-09 21:13:59 +000012568 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012569 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
12570 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012571 if (doc == NULL) {
12572 xmlSchemaPErr(ctxt, NULL,
12573 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012574 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012575 NULL, NULL);
12576 return (NULL);
12577 }
12578 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000012579 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000012580 } else if (ctxt->doc != NULL) {
12581 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012582 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000012583 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012584 xmlSchemaPErr(ctxt, NULL,
12585 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012586 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012587 NULL, NULL);
12588 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000012589 }
12590
12591 /*
12592 * Then extract the root and Schema parse it
12593 */
12594 root = xmlDocGetRootElement(doc);
12595 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012596 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
12597 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012598 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000012599 if (!preserve) {
12600 xmlFreeDoc(doc);
12601 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012602 return (NULL);
12603 }
12604
12605 /*
12606 * Remove all the blank text nodes
12607 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000012608 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000012609
12610 /*
12611 * Then do the parsing for good
12612 */
12613 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000012614 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000012615 if (!preserve) {
12616 xmlFreeDoc(doc);
12617 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012618 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000012619 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012620 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000012621 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000012622 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012623 ctxt->ctxtType = NULL;
12624 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012625 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000012626 * Then fixup all attributes declarations
12627 */
12628 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
12629
12630 /*
12631 * Then fixup all attributes group declarations
12632 */
12633 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
12634 ctxt);
12635
12636 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012637 * Check attribute groups for circular references.
12638 */
12639 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
12640 xmlSchemaCheckAttributeGroupCircular, ctxt);
12641
12642 /*
12643 * Then fixup all model group definitions.
12644 */
12645 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012646
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012647 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000012648 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012650 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012651
12652 /*
12653 * Then fix references of element declaration; apply constraints.
12654 */
12655 xmlHashScanFull(ret->elemDecl,
12656 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012657
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012658 /*
12659 * Check model groups defnitions for circular references.
12660 */
12661 xmlHashScan(ret->groupDecl, (xmlHashScanner)
12662 xmlSchemaCheckGroupDefCircular, ctxt);
12663
Daniel Veillard4255d502002-04-16 15:50:10 +000012664 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012665 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000012666 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012667 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012668 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012669
12670 /*
12671 * Then check the defaults part of the type like facets values
12672 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012673 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults,
12674 ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000012675
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012677 if (ctxt->nberrors != 0) {
12678 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012679 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000012680 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012681 return (ret);
12682}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012683
Daniel Veillard4255d502002-04-16 15:50:10 +000012684/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000012685 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000012686 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000012687 * @err: the error callback
12688 * @warn: the warning callback
12689 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000012690 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000012691 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000012692 */
12693void
12694xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012695 xmlSchemaValidityErrorFunc err,
12696 xmlSchemaValidityWarningFunc warn, void *ctx)
12697{
Daniel Veillard4255d502002-04-16 15:50:10 +000012698 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012699 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012700 ctxt->error = err;
12701 ctxt->warning = warn;
12702 ctxt->userData = ctx;
12703}
12704
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012705/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000012706 * xmlSchemaGetParserErrors:
12707 * @ctxt: a XMl-Schema parser context
12708 * @err: the error callback result
12709 * @warn: the warning callback result
12710 * @ctx: contextual data for the callbacks result
12711 *
12712 * Get the callback information used to handle errors for a parser context
12713 *
12714 * Returns -1 in case of failure, 0 otherwise
12715 */
12716int
12717xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
12718 xmlSchemaValidityErrorFunc * err,
12719 xmlSchemaValidityWarningFunc * warn, void **ctx)
12720{
12721 if (ctxt == NULL)
12722 return(-1);
12723 if (err != NULL)
12724 *err = ctxt->error;
12725 if (warn != NULL)
12726 *warn = ctxt->warning;
12727 if (ctx != NULL)
12728 *ctx = ctxt->userData;
12729 return(0);
12730}
12731
12732/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012733 * xmlSchemaFacetTypeToString:
12734 * @type: the facet type
12735 *
12736 * Convert the xmlSchemaTypeType to a char string.
12737 *
12738 * Returns the char string representation of the facet type if the
12739 * type is a facet and an "Internal Error" string otherwise.
12740 */
12741static const char *
12742xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
12743{
12744 switch (type) {
12745 case XML_SCHEMA_FACET_PATTERN:
12746 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012747 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012748 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012749 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012750 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012751 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012752 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012754 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012755 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012756 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012758 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012759 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012760 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012761 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012762 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012763 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012764 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012765 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012766 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012767 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012768 return ("fractionDigits");
12769 default:
12770 break;
12771 }
12772 return ("Internal Error");
12773}
12774
Daniel Veillardc0826a72004-08-10 14:17:33 +000012775static xmlChar *
12776xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
12777 const xmlChar *cur = value;
12778 xmlChar *ret = NULL, *mcur;
12779
12780 if (value == NULL)
12781 return(NULL);
12782
12783 while ((*cur != 0) &&
12784 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
12785 cur++;
12786 }
12787 if (*cur == 0)
12788 return (NULL);
12789 ret = xmlStrdup(value);
12790 /* TODO FIXME: I guess gcc will bark at this. */
12791 mcur = (xmlChar *) (ret + (cur - value));
12792 do {
12793 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
12794 *mcur = ' ';
12795 mcur++;
12796 } while (*mcur != 0);
12797 return(ret);
12798}
12799
12800static int
12801xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
12802{
12803 xmlSchemaTypePtr anc;
12804
12805 /*
12806 * The normalization type can be changed only for types which are derived
12807 * from xsd:string.
12808 */
12809 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12810 if ((type->builtInType == XML_SCHEMAS_STRING) &&
12811 (type->builtInType == XML_SCHEMAS_NORMSTRING))
12812
12813 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12814 else {
12815 /*
12816 * For all ·atomic· datatypes other than string (and types ·derived·
12817 * by ·restriction· from it) the value of whiteSpace is fixed to
12818 * collapse
12819 */
12820 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12821 }
12822 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12823 /*
12824 * For list types the facet "whiteSpace" is fixed to "collapse".
12825 */
12826 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12827 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12828 return (-1);
12829 } else if (type->facetSet != NULL) {
12830 xmlSchemaTypePtr anyST;
12831 xmlSchemaFacetLinkPtr lin;
12832
12833 /*
12834 * Atomic types.
12835 */
12836 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12837 anc = type->baseType;
12838 do {
12839 /*
12840 * For all ·atomic· datatypes other than string (and types ·derived·
12841 * by ·restriction· from it) the value of whiteSpace is fixed to
12842 * collapse
12843 */
12844 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
12845 (anc->builtInType == XML_SCHEMAS_STRING)) {
12846
12847 lin = type->facetSet;
12848 do {
12849 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
12850 if (lin->facet->whitespace ==
12851 XML_SCHEMAS_FACET_COLLAPSE) {
12852 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12853 } else if (lin->facet->whitespace ==
12854 XML_SCHEMAS_FACET_REPLACE) {
12855 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
12856 } else
12857 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
12858 break;
12859 }
12860 lin = lin->next;
12861 } while (lin != NULL);
12862 break;
12863 }
12864 anc = anc->baseType;
12865 } while (anc != anyST);
12866 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
12867 }
12868 return (-1);
12869}
12870
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012871/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000012872 * xmlSchemaValidateFacetsInternal:
12873 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000012874 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000012875 * @facets: the list of facets to check
12876 * @value: the lexical repr of the value to validate
12877 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000012878 * @fireErrors: if 0, only internal errors will be fired;
12879 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000012880 *
12881 * Check a value against all facet conditions
12882 *
12883 * Returns 0 if the element is schemas valid, a positive error code
12884 * number otherwise and -1 in case of internal or API error.
12885 */
12886static int
12887xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012888 xmlSchemaTypePtr type,
12889 const xmlChar * value,
12890 unsigned long length,
12891 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012892{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012893 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012894 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012895 xmlSchemaTypePtr biType; /* The build-in type. */
12896 xmlSchemaTypePtr tmpType;
12897 xmlSchemaFacetLinkPtr facetLink;
12898 int retFacet, hasFacet;
12899 xmlSchemaFacetPtr facet;
12900 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012901
Daniel Veillardc0826a72004-08-10 14:17:33 +000012902#ifdef DEBUG_UNION_VALIDATION
12903 printf("Facets of type: '%s'\n", (const char *) type->name);
12904 printf(" fireErrors: %d\n", fireErrors);
12905#endif
12906
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012907 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012908 /*
12909 * NOTE: Do not jump away, if the facetSet of the given type is
12910 * empty: until now, "pattern" facets of the *base types* need to
12911 * be checked as well.
12912 */
12913 biType = type->baseType;
12914 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
12915 biType = biType->baseType;
12916 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012917 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012918 "Internal error: xmlSchemaValidateFacetsInternal, "
12919 "the base type axis of the given type '%s' does not resolve to "
12920 "a built-in type.\n",
12921 type->name, NULL);
12922 return (-1);
12923 }
12924
12925 if (type->facetSet != NULL) {
12926 facetLink = type->facetSet;
12927 while (facetLink != NULL) {
12928 facet = facetLink->facet;
12929 /*
12930 * Skip the pattern "whiteSpace": it is used to
12931 * format the character content beforehand.
12932 */
12933 switch (facet->type) {
12934 case XML_SCHEMA_FACET_WHITESPACE:
12935 case XML_SCHEMA_FACET_PATTERN:
12936 case XML_SCHEMA_FACET_ENUMERATION:
12937 break;
12938 case XML_SCHEMA_FACET_LENGTH:
12939 case XML_SCHEMA_FACET_MINLENGTH:
12940 case XML_SCHEMA_FACET_MAXLENGTH:
12941 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12942 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
12943 value, length, 0);
12944 len = length;
12945 } else
12946 ret = xmlSchemaValidateLengthFacet(biType, facet,
12947 value, ctxt->value, &len);
12948 break;
12949 default:
12950 ret = xmlSchemaValidateFacet(biType, facet, value,
12951 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012952 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012953 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012954 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012955 "Internal error: xmlSchemaValidateFacetsInternal, "
12956 "validating facet of type '%s'.\n",
12957 type->name, NULL);
12958 break;
12959 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012960 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012961 type, facet, NULL, NULL, NULL, NULL);
12962 }
12963
12964 facetLink = facetLink->next;
12965 }
12966 if (ret >= 0) {
12967 /*
12968 * Process enumerations.
12969 */
12970 retFacet = 0;
12971 facetLink = type->facetSet;
12972 while (facetLink != NULL) {
12973 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
12974 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
12975 value, ctxt->value);
12976 if (retFacet <= 0)
12977 break;
12978 }
12979 facetLink = facetLink->next;
12980 }
12981 if (retFacet > 0) {
12982 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
12983 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012984 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012985 value, 0, type, NULL, NULL, NULL, NULL, NULL);
12986 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012987 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012988 "Internal error: xmlSchemaValidateFacetsInternal, "
12989 "validating facet of type '%s'.\n",
12990 BAD_CAST "enumeration", NULL);
12991 ret = -1;
12992 }
12993 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000012994 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012995 if (ret >= 0) {
12996 /*
12997 * Process patters. Pattern facets are ORed at type level
12998 * and ANDed if derived. Walk the base type axis.
12999 */
13000 hasFacet = 0;
13001 tmpType = type;
13002 facet = NULL;
13003 do {
13004 retFacet = 0;
13005 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013006 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013007 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13008 continue;
13009 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13010 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013011 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013012 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013013 else if (retFacet < 0) {
13014 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13015 "Internal error: xmlSchemaValidateFacetsInternal, "
13016 "validating 'pattern' facet '%s' of type '%s'.\n",
13017 facetLink->facet->value, tmpType->name);
13018 ret = -1;
13019 break;
13020 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013021 /* Save the last non-validating facet. */
13022 facet = facetLink->facet;
13023 }
13024 if (retFacet != 0)
13025 break;
13026 tmpType = tmpType->baseType;
13027 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013028 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013029 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13030 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013031 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013032 NULL, NULL, NULL, NULL);
13033 }
13034 }
13035 }
13036
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013037 return (ret);
13038}
13039
Daniel Veillard4255d502002-04-16 15:50:10 +000013040/************************************************************************
13041 * *
13042 * Simple type validation *
13043 * *
13044 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013045
Daniel Veillard4255d502002-04-16 15:50:10 +000013046
13047/************************************************************************
13048 * *
13049 * DOM Validation code *
13050 * *
13051 ************************************************************************/
13052
Daniel Veillard4255d502002-04-16 15:50:10 +000013053static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013054 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013055 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013056static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
13057 xmlSchemaTypePtr type);
Daniel Veillard4255d502002-04-16 15:50:10 +000013058
Daniel Veillard3646d642004-06-02 19:19:14 +000013059
13060/**
13061 * xmlSchemaFreeAttrStates:
13062 * @state: a list of attribute states
13063 *
13064 * Free the given list of attribute states
13065 *
13066 */
13067static void
13068xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13069{
13070 xmlSchemaAttrStatePtr tmp;
13071 while (state != NULL) {
13072 tmp = state;
13073 state = state->next;
13074 xmlFree(tmp);
13075 }
13076}
13077
Daniel Veillard4255d502002-04-16 15:50:10 +000013078/**
13079 * xmlSchemaRegisterAttributes:
13080 * @ctxt: a schema validation context
13081 * @attrs: a list of attributes
13082 *
13083 * Register the list of attributes as the set to be validated on that element
13084 *
13085 * Returns -1 in case of error, 0 otherwise
13086 */
13087static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013088xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13089{
Daniel Veillard3646d642004-06-02 19:19:14 +000013090 xmlSchemaAttrStatePtr tmp;
13091
13092 ctxt->attr = NULL;
13093 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013094 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013095 if ((attrs->ns != NULL) &&
13096 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13097 attrs = attrs->next;
13098 continue;
13099 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013100 tmp = (xmlSchemaAttrStatePtr)
13101 xmlMalloc(sizeof(xmlSchemaAttrState));
13102 if (tmp == NULL) {
13103 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13104 return (-1);
13105 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013106 tmp->attr = attrs;
13107 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13108 tmp->next = NULL;
13109 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013110 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013111 else
13112 ctxt->attrTop->next = tmp;
13113 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013114 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013115 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013116 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013117}
13118
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013119#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013120/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013121 * xmlSchemaValidateCheckNodeList
13122 * @nodelist: the list of nodes
13123 *
13124 * Check the node list is only made of text nodes and entities pointing
13125 * to text nodes
13126 *
13127 * Returns 1 if true, 0 if false and -1 in case of error
13128 */
13129static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013130xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13131{
Daniel Veillard4255d502002-04-16 15:50:10 +000013132 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013133 if (nodelist->type == XML_ENTITY_REF_NODE) {
13134 TODO /* implement recursion in the entity content */
13135 }
13136 if ((nodelist->type != XML_TEXT_NODE) &&
13137 (nodelist->type != XML_COMMENT_NODE) &&
13138 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013139 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013140 return (0);
13141 }
13142 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013143 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013144 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000013145}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013146#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013147
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013148static void
13149xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
13150{
13151 int i, nbItems;
13152 xmlSchemaTypePtr item, *items;
13153
13154
13155 /*
13156 * During the Assemble of the schema ctxt->curItems has
13157 * been filled with the relevant new items. Fix those up.
13158 */
13159 nbItems = ctxt->assemble->nbItems;
13160 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
13161
13162 for (i = 0; i < nbItems; i++) {
13163 item = items[i];
13164 switch (item->type) {
13165 case XML_SCHEMA_TYPE_ATTRIBUTE:
13166 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
13167 break;
13168 case XML_SCHEMA_TYPE_ELEMENT:
13169 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
13170 NULL, NULL, NULL);
13171 break;
13172 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13173 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
13174 ctxt, NULL);
13175 break;
13176 case XML_SCHEMA_TYPE_GROUP:
13177 xmlSchemaGroupDefFixup(item, ctxt, NULL);
13178 default:
13179 break;
13180 }
13181 }
13182 /*
13183 * Circularity checks.
13184 */
13185 for (i = 0; i < nbItems; i++) {
13186 item = items[i];
13187 switch (item->type) {
13188 case XML_SCHEMA_TYPE_GROUP:
13189 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
13190 break;
13191 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
13192 xmlSchemaCheckAttributeGroupCircular(
13193 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
13194 break;
13195 default:
13196 break;
13197 }
13198 }
13199 /*
13200 * Fixup for all other item.
13201 * TODO: Hmm, not sure if starting from complex/simple types,
13202 * all subsequent items will be reached.
13203 */
13204 for (i = 0; i < nbItems; i++) {
13205 item = items[i];
13206 switch (item->type) {
13207 case XML_SCHEMA_TYPE_SIMPLE:
13208 case XML_SCHEMA_TYPE_COMPLEX:
13209 xmlSchemaTypeFixup(item, ctxt, NULL);
13210 break;
13211 default:
13212 break;
13213 }
13214 }
13215 /*
13216 * Check facet values. Note that facets are
13217 * hold by complex and simple type components only.
13218 */
13219 for (i = 0; i < nbItems; i++) {
13220 item = items[i];
13221 switch (item->type) {
13222 case XML_SCHEMA_TYPE_SIMPLE:
13223 case XML_SCHEMA_TYPE_COMPLEX:
13224 xmlSchemaCheckDefaults(item, ctxt, NULL);
13225 break;
13226 default:
13227 break;
13228 }
13229 }
13230 /*
13231 * Build the content model for complex types.
13232 */
13233 for (i = 0; i < nbItems; i++) {
13234 item = items[i];
13235 switch (item->type) {
13236 case XML_SCHEMA_TYPE_COMPLEX:
13237 xmlSchemaBuildContentModel(item, ctxt, NULL);
13238 break;
13239 default:
13240 break;
13241 }
13242 }
13243}
13244
13245/**
13246 * xmlSchemaAssembleByLocation:
13247 * @pctxt: a schema parser context
13248 * @vctxt: a schema validation context
13249 * @schema: the existing schema
13250 * @node: the node that fired the assembling
13251 * @nsName: the namespace name of the new schema
13252 * @location: the location of the schema
13253 *
13254 * Expands an existing schema by an additional schema.
13255 *
13256 * Returns 0 if the new schema is correct, a positive error code
13257 * number otherwise and -1 in case of an internal or API error.
13258 */
13259static int
13260xmlSchemaAssembleByLocation(xmlSchemaParserCtxtPtr pctxt,
13261 xmlSchemaValidCtxtPtr vctxt,
13262 xmlSchemaPtr schema,
13263 xmlNodePtr node,
13264 const xmlChar *nsName,
13265 const xmlChar *location)
13266{
13267 const xmlChar *targetNs, *oldtns;
13268 xmlDocPtr doc, olddoc;
13269 int oldflags, ret = 0, reuseCtxt;
13270 xmlNodePtr docElem;
13271 /*
13272 * This should be used:
13273 * 1. on <import>(s)
13274 * 2. if requested by the validated instance
13275 * 3. if requested via the API
13276 */
13277 if ((pctxt == NULL) && (vctxt == NULL))
13278 return (-1);
13279 /*
13280 * Create a temporary parser context.
13281 * TODO: what to set exaclty for the URL argument here?
13282 */
13283 if (pctxt == NULL) {
13284 reuseCtxt = 0;
13285 pctxt = xmlSchemaNewParserCtxtUseDict((const char *) location, schema->dict);
13286 if (pctxt == NULL) {
13287 xmlSchemaVErrMemory(vctxt,
13288 "xmlSchemaAssembleByLocation, allocating new parser "
13289 "content for dynamic construction of schemata", NULL);
13290 return (-1);
13291 }
13292 pctxt->error = vctxt->error;
13293 pctxt->warning = vctxt->warning;
13294 } else
13295 reuseCtxt = 1;
13296 /*
13297 * Acquire the schema document.
13298 */
13299 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
13300 nsName, location, &doc, &targetNs, 0);
13301 if (ret != 0) {
13302 if (doc != NULL)
13303 xmlFreeDoc(doc);
13304 } else if (doc != NULL) {
13305 docElem = xmlDocGetRootElement(doc);
13306 /*
13307 * Save and reset the context & schema.
13308 */
13309 oldflags = schema->flags;
13310 oldtns = schema->targetNamespace;
13311 olddoc = schema->doc;
13312
13313 xmlSchemaClearSchemaDefaults(schema);
13314 schema->targetNamespace = targetNs;
13315 /* schema->nbCurItems = 0; */
13316 pctxt->schema = schema;
13317 if (pctxt->assemble == NULL) {
13318 pctxt->assemble = xmlSchemaNewAssemble();
13319 xmlSchemaVErrMemory(vctxt,
13320 "Memory error: xmlSchemaAssembleByLocation, "
13321 "allocating assemble info", NULL);
13322 return (-1);
13323 }
13324 pctxt->ctxtType = NULL;
13325 pctxt->parentItem = NULL;
13326
13327 xmlSchemaParseSchemaDefaults(pctxt, pctxt->schema, docElem);
13328 xmlSchemaParseSchemaTopLevel(pctxt, pctxt->schema, docElem->children);
13329 xmlSchemaPostSchemaAssembleFixup(pctxt);
13330 /*
13331 * Free the list of assembled components.
13332 */
13333 xmlFree(pctxt->assemble->items);
13334 /*
13335 * Restore the context & schema.
13336 */
13337 schema->flags = oldflags;
13338 schema->targetNamespace = oldtns;
13339 schema->doc = olddoc;
13340 ret = pctxt->err;
13341 }
13342 if (reuseCtxt == 0) {
13343 pctxt->dict = NULL;
13344 xmlSchemaFreeParserCtxt(pctxt);
13345 }
13346 return (ret);
13347}
13348
13349/**
13350 * xmlSchemaAssembleByXSIAttr:
13351 * @vctxt: a schema validation context
13352 * @xsiAttr: an xsi attribute
13353 * @noNamespace: whether a schema with no target namespace is exptected
13354 *
13355 * Expands an existing schema by an additional schema using
13356 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
13357 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
13358 * must be set to 1.
13359 *
13360 * Returns 0 if the new schema is correct, a positive error code
13361 * number otherwise and -1 in case of an internal or API error.
13362 */
13363static int
13364xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
13365 xmlAttrPtr xsiAttr,
13366 int noNamespace)
13367{
13368 xmlChar *value;
13369 const xmlChar *cur, *end;
13370 const xmlChar *nsname = NULL, *location;
13371 int count = 0;
13372 int ret = 0;
13373
13374 if (xsiAttr == NULL) {
13375 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
13376 NULL, NULL,
13377 "Internal error: xmlSchemaAssembleByXSIAttr, "
13378 "bad arguments", NULL);
13379 return (-1);
13380 }
13381 /*
13382 * Parse the value; we will assume an even number of values
13383 * to be given (this is how Xerces and XSV work).
13384 */
13385 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
13386 cur = value;
13387 do {
13388 if (noNamespace != 1) {
13389 /*
13390 * Get the namespace name.
13391 */
13392 while (IS_BLANK_CH(*cur))
13393 cur++;
13394 end = cur;
13395 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13396 end++;
13397 if (end == cur)
13398 break;
13399 count++;
13400 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
13401 cur = end;
13402 }
13403 /*
13404 * Get the URI.
13405 */
13406 while (IS_BLANK_CH(*cur))
13407 cur++;
13408 end = cur;
13409 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13410 end++;
13411 if (end == cur)
13412 break;
13413 count++;
13414 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
13415 cur = end;
13416 ret = xmlSchemaAssembleByLocation(NULL, vctxt, vctxt->schema,
13417 xsiAttr->parent, nsname, location);
13418 if (ret == -1) {
13419 xmlSchemaVCustomErr(vctxt,
13420 XML_SCHEMAV_INTERNAL,
13421 (xmlNodePtr) xsiAttr, NULL,
13422 "Internal error: xmlSchemaAssembleByXSIAttr, "
13423 "assembling schemata", NULL);
13424 if (value != NULL)
13425 xmlFree(value);
13426 return (-1);
13427 }
13428 } while (*cur != 0);
13429 if (value != NULL)
13430 xmlFree(value);
13431 return (ret);
13432}
13433
13434/**
13435 * xmlSchemaAssembleByXSIElem:
13436 * @vctxt: a schema validation context
13437 * @elem: an element node possibly holding xsi attributes
13438 * @noNamespace: whether a schema with no target namespace is exptected
13439 *
13440 * Assembles an existing schema by an additional schema using
13441 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
13442 * of the given @elem.
13443 *
13444 * Returns 0 if the new schema is correct, a positive error code
13445 * number otherwise and -1 in case of an internal or API error.
13446 */
13447static int
13448xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
13449 xmlNodePtr elem)
13450{
13451 int ret = 0, retNs = 0;
13452 xmlAttrPtr attr;
13453
13454 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
13455 if (attr != NULL) {
13456 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
13457 if (retNs == -1)
13458 return (-1);
13459 }
13460 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
13461 if (attr != NULL) {
13462 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
13463 if (ret == -1)
13464 return (-1);
13465 }
13466 if (retNs != 0)
13467 return (retNs);
13468 else
13469 return (ret);
13470}
13471
Daniel Veillard4255d502002-04-16 15:50:10 +000013472/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013473 * xmlSchemaValidateCallback:
13474 * @ctxt: a schema validation context
13475 * @name: the name of the element detected (might be NULL)
13476 * @type: the type
13477 *
13478 * A transition has been made in the automata associated to an element
13479 * content model
13480 */
13481static void
13482xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013483 const xmlChar * name ATTRIBUTE_UNUSED,
13484 xmlSchemaTypePtr type, xmlNodePtr node)
13485{
Daniel Veillard4255d502002-04-16 15:50:10 +000013486 xmlSchemaTypePtr oldtype = ctxt->type;
13487 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013488
Daniel Veillard4255d502002-04-16 15:50:10 +000013489#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000013490 xmlGenericError(xmlGenericErrorContext,
13491 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013492 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000013493#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013494 /*
13495 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
13496 */
Daniel Veillard4255d502002-04-16 15:50:10 +000013497 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013498 ctxt->node = node;
13499 ctxt->cur = node->children;
13500 /*
13501 * Assemble new schemata using xsi.
13502 */
13503 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
13504 int ret;
13505
13506 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
13507 if (ret == -1) {
13508 xmlSchemaVCustomErr(ctxt,
13509 XML_SCHEMAV_INTERNAL,
13510 ctxt->node, NULL,
13511 "Internal error: xmlSchemaValidateElement, "
13512 "assembling schema by xsi", NULL);
13513 return;
13514 }
13515 /*
13516 * NOTE: We won't react on schema parser errors here.
13517 * TODO: But a warning would be nice.
13518 */
13519 }
13520 switch (type->type) {
13521 case XML_SCHEMA_TYPE_ELEMENT: {
13522 /*
13523 * NOTE: The build of the content model
13524 * (xmlSchemaBuildAContentModel) ensures that the element
13525 * declaration (and not a reference to it) will be given.
13526 */
13527 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
13528 /*
13529 * This is paranoid coding ;-)... it should not
13530 * happen here any more.
13531 */
13532 xmlSchemaVCustomErr(ctxt,
13533 XML_SCHEMAV_INTERNAL,
13534 node, NULL,
13535 "Internal error: xmlSchemaValidateCallback, "
13536 "element declaration 'reference' encountered, "
13537 "but an element declaration was expected",
13538 NULL);
13539 return;
13540 }
13541 xmlSchemaValidateElementByDeclaration(ctxt,
13542 (xmlSchemaElementPtr) type);
13543 break;
13544 }
13545 case XML_SCHEMA_TYPE_ANY:
13546 xmlSchemaValidateElementByWildcard(ctxt, type);
13547 break;
13548 default:
13549 break;
13550 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013551 ctxt->type = oldtype;
13552 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013553}
Daniel Veillard4255d502002-04-16 15:50:10 +000013554
Daniel Veillard01fa6152004-06-29 17:04:39 +000013555/**
13556 * xmlSchemaValidateSimpleTypeValue:
13557 * @ctxt: a schema validation context
13558 * @value: the value to be validated
13559 * @fireErrors: shall errors be reported?
13560 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000013561 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013562 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000013563 *
13564 * Validates a value by the given type (user derived or built-in).
13565 *
13566 * Returns 0 if the value is valid, a positive error code
13567 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 */
13569static int
13570xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013571 xmlSchemaTypePtr type,
13572 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013574 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013575 int normalize,
13576 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013578 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013579 int ret = 0;
13580 xmlChar *normValue = NULL;
13581 int wtsp;
13582
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013583 node = ctxt->node;
13584 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013585 wtsp = ctxt->valueWS;
13586 /*
13587 * Normalize the value.
13588 */
13589 if (normalize &&
13590 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
13591 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
13592
13593 if ((norm != -1) && (norm > ctxt->valueWS)) {
13594 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
13595 normValue = xmlSchemaCollapseString(value);
13596 else
13597 normValue = xmlSchemaWhiteSpaceReplace(value);
13598 ctxt->valueWS = norm;
13599 if (normValue != NULL)
13600 value = (const xmlChar *) normValue;
13601 }
13602 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013603 /*
13604 * The nodes of a content must be checked only once,
13605 * this is not working since list types will fire this
13606 * multiple times.
13607 */
13608 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
13609 xmlNodePtr cur = ctxt->cur;
13610
13611 do {
13612 switch (cur->type) {
13613 case XML_TEXT_NODE:
13614 case XML_CDATA_SECTION_NODE:
13615 case XML_PI_NODE:
13616 case XML_COMMENT_NODE:
13617 case XML_XINCLUDE_START:
13618 case XML_XINCLUDE_END:
13619 break;
13620 case XML_ENTITY_REF_NODE:
13621 case XML_ENTITY_NODE:
13622 /* TODO: Scour the entities for illegal nodes. */
13623 TODO break;
13624 case XML_ELEMENT_NODE: {
13625 /* NOTE: Changed to an internal error, since the
13626 * existence of an element node will be already checked in
13627 * xmlSchemaValidateElementBySimpleType and in
13628 * xmlSchemaValidateElementByComplexType.
13629 */
13630 xmlSchemaVCustomErr(ctxt,
13631 XML_SCHEMAV_INTERNAL,
13632 /* XML_SCHEMAS_ERR_INVALIDELEM, */
13633 node, type,
13634 "Element '%s' found in simple type content",
13635 cur->name);
13636 return (XML_SCHEMAV_INTERNAL);
13637 }
13638 case XML_ATTRIBUTE_NODE:
13639 case XML_DOCUMENT_NODE:
13640 case XML_DOCUMENT_TYPE_NODE:
13641 case XML_DOCUMENT_FRAG_NODE:
13642 case XML_NOTATION_NODE:
13643 case XML_HTML_DOCUMENT_NODE:
13644 case XML_DTD_NODE:
13645 case XML_ELEMENT_DECL:
13646 case XML_ATTRIBUTE_DECL:
13647 case XML_ENTITY_DECL:
13648 case XML_NAMESPACE_DECL:
13649#ifdef LIBXML_DOCB_ENABLED
13650 case XML_DOCB_DOCUMENT_NODE:
13651#endif
13652 xmlSchemaVCustomErr(ctxt,
13653 XML_SCHEMAV_INTERNAL,
13654 /* XML_SCHEMAS_ERR_INVALIDELEM, */
13655 node, NULL,
13656 "Node of unexpected type found in simple type content",
13657 NULL);
13658 return (XML_SCHEMAV_INTERNAL);
13659 }
13660 cur = cur->next;
13661 } while (cur != NULL);
13662 }
13663
William M. Brack2f2a6632004-08-20 23:09:47 +000013664 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
13665 xmlSchemaTypePtr base, anyType;
13666
13667 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13668
13669 base = type->baseType;
13670 while ((base != NULL) &&
13671 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
13672 (base->type != XML_SCHEMA_TYPE_BASIC) &&
13673 (base != anyType)) {
13674 base = base->baseType;
13675 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013676 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013677 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013678 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013679 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13680 "validating complex type '%s'\n",
13681 type->name, NULL);
13682 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
13683 /*
13684 * Check facets.
13685 */
13686 /*
13687 * This is somehow not nice, since if an error occurs
13688 * the reported type will be the complex type; the spec
13689 * wants a simple type to be created on the complex type
13690 * if it has a simple content. For now we have to live with
13691 * it.
13692 */
13693 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13694 value, 0, fireErrors);
13695 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013696 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013697 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13698 "validating facets of complex type '%s'\n",
13699 type->name, NULL);
13700 } else if (ret > 0) {
13701 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000013702 if (fireErrors)
13703 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000013704 }
13705 }
13706 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013707
13708 if (ctxt->value != NULL) {
13709 xmlSchemaFreeValue(ctxt->value);
13710 ctxt->value = NULL;
13711 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013712 /*
13713 * STREAM-READ-CHILDREN.
13714 */
13715 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013716 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013717 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
13718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
13719 else
13720 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013721 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013722 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013723 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013724 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 }
13728 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13729 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
13730 * a literal in the ·lexical space· of {base type definition}
13731 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013732 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013734 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013736 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013738 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013740 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013741 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013742 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013744 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013746 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13747 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013749 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013751 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 type->name, NULL);
13753 } else if (ret > 0) {
13754 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013755 /*
13756 Disabled, since the facet validation already reports errors.
13757 if (fireErrors)
13758 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13759 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013760 }
13761 }
13762 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13763
13764 xmlSchemaTypePtr tmpType;
13765 const xmlChar *cur, *end;
13766 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013767 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768
13769 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
13770 * of white space separated tokens, each of which ·match·es a literal
13771 * in the ·lexical space· of {item type definition}
13772 */
13773
Daniel Veillardc0826a72004-08-10 14:17:33 +000013774 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013775 cur = value;
13776 do {
13777 while (IS_BLANK_CH(*cur))
13778 cur++;
13779 end = cur;
13780 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
13781 end++;
13782 if (end == cur)
13783 break;
13784 tmp = xmlStrndup(cur, end - cur);
13785 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013786 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013789 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013790 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13791 "validating an item of list simple type '%s'\n",
13792 type->name, NULL);
13793 break;
13794 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013796 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013797 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013799 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 cur = end;
13801 } while (*cur != 0);
13802 /*
13803 * Check facets.
13804 */
13805 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013806 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 } else if ((ret == 0) && (applyFacets)) {
13811 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13812 value, len, fireErrors);
13813 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013814 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013815 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13816 "validating facets of list simple type '%s'\n",
13817 type->name, NULL);
13818 } else if (ret > 0) {
13819 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013820 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013821 Disabled, since the facet validation already reports errors.
13822 if (fireErrors)
13823 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013824 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013825 }
13826
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 }
13828 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13829 xmlSchemaTypeLinkPtr memberLink;
13830
13831 /*
13832 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
13833 * not apply directly; however, the normalization behavior of ·union·
13834 * types is controlled by the value of whiteSpace on that one of the
13835 * ·memberTypes· against which the ·union· is successfully validated.
13836 *
13837 * This means that the value is normalized by the first validating
13838 * member type, then the facets of the union type are applied. This
13839 * needs changing of the value!
13840 */
13841
13842 /*
13843 * 1.2.3 if {variety} is ·union· then the string must ·match· a
13844 * literal in the ·lexical space· of at least one member of
13845 * {member type definitions}
13846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013847#ifdef DEBUG_UNION_VALIDATION
13848 printf("Union ST : '%s'\n", (const char *) type->name);
13849 printf(" fireErrors : %d\n", fireErrors);
13850 printf(" applyFacets: %d\n", applyFacets);
13851#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000013852 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
13853 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013854 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013856 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013857 type->name, NULL);
13858 ret = -1;
13859 }
13860 if (ret == 0) {
13861 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013862 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
13863 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 if ((ret <= 0) || (ret == 0))
13865 break;
13866 memberLink = memberLink->next;
13867 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013869 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013871 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013872 type->name, NULL);
13873 } else if (ret > 0) {
13874 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013875 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013876 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013877 }
13878 }
13879 /*
13880 * Apply facets (pattern, enumeration).
13881 */
13882 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
13883 int mws;
13884 /*
13885 * The normalization behavior of ·union· types is controlled by
13886 * the value of whiteSpace on that one of the ·memberTypes·
13887 * against which the ·union· is successfully validated.
13888 */
13889 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013890 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013891 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13892 "the value was already normalized for the union simple "
13893 "type '%s'.\n", type->name, NULL);
13894 }
13895 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
13896 if (mws > ctxt->valueWS) {
13897 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
13898 normValue = xmlSchemaCollapseString(value);
13899 else
13900 normValue = xmlSchemaWhiteSpaceReplace(value);
13901 if (normValue != NULL)
13902 value = (const xmlChar *) normValue;
13903 }
13904
13905 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
13906 value, 0, fireErrors);
13907 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013908 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013909 "Internal error: xmlSchemaValidateSimpleTypeValue, "
13910 "validating facets of union simple type '%s'\n",
13911 type->name, NULL);
13912 } else if (ret > 0) {
13913 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
13914 /*
13915 if (fireErrors)
13916 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
13917 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013918 }
13919 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013920 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013921 ctxt->valueWS = wtsp;
13922 if (normValue != NULL)
13923 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013924 return (ret);
13925}
13926
13927/**
13928 * xmlSchemaValidateSimpleTypeElement:
13929 * @ctxt: a schema validation context
13930 * @node: the element node to be validated.
13931 *
13932 * Validate the element against a simple type.
13933 *
13934 * Returns 0 if the element is valid, a positive error code
13935 * number otherwise and -1 in case of an internal or API error.
13936 */
13937static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013938xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
13939 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013940{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013941 xmlSchemaTypePtr oldtype;
13942 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013943 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013944 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013945 int ret = 0, retval = 0;
13946
Daniel Veillard01fa6152004-06-29 17:04:39 +000013947 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013948 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
13949 "Internal error: xmlSchemaValidateElementBySimpleType, "
13950 "bad arguments", NULL);
13951 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013952 }
13953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013954 oldtype = ctxt->type;
13955 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013956 /*
13957 * cvc-type: 3.1.2 The element information item must have no element
13958 * information item [children].
13959 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013960 /*
13961 * STREAM: Child nodes are processed.
13962 */
13963 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013964 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013965 /*
13966 * TODO: Entities, will they produce elements as well?
13967 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013968 if (cur->type == XML_ELEMENT_NODE) {
13969 xmlSchemaVCustomErr(ctxt,
13970 XML_SCHEMAV_CVC_TYPE_3_1_2,
13971 node, type,
13972 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013973 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013974 }
13975 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013976 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013977
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013979 * cvc-type 3.1.1:
13980 *
13981 * The attributes of must be empty, excepting those whose namespace name
13982 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
13983 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013984 */
13985 /*
13986 * STREAM: Attribute nodes are processed.
13987 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 attr = node->properties;
13989 while (attr != NULL) {
13990 if ((attr->ns == NULL) ||
13991 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
13992 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
13993 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
13994 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
13995 (!xmlStrEqual
13996 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013997 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013998 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
13999 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014000 }
14001 attr = attr->next;
14002 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014003 /*
14004 * This will skip validation if the type is 'anySimpleType'.
14005 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014006 if ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14007 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014008 xmlChar *value;
14009
14010 value = xmlNodeGetContent(node);
14011 /*
14012 * NOTE: This call will not check the content nodes, since
14013 * this should be checked here already.
14014 */
14015 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14016 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014017 if (value != NULL)
14018 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014019 if (retval != 0)
14020 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014021 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014022 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014023 return (ret);
14024}
Daniel Veillard4255d502002-04-16 15:50:10 +000014025
14026/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014027 * xmlSchemaValQNameAcquire:
14028 * @value: the lexical represantation of the QName value
14029 * @node: the node to search for the corresponding namespace declaration
14030 * @nsName: the resulting namespace name if found
14031 *
14032 * Checks that a value conforms to the lexical space of the type QName;
14033 * if valid, the corresponding namespace name is searched and retured
14034 * as a copy in @nsName. The local name is returned in @localName as
14035 * a copy.
14036 *
14037 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14038 * namespace declaration was found in scope; -1 in case of an internal or
14039 * API error.
14040 */
14041static int
14042xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14043 xmlChar **nsName, xmlChar **localName)
14044{
14045 int ret;
14046 xmlChar *local = NULL;
14047
14048 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14049 return (-1);
14050 *nsName = NULL;
14051 *localName = NULL;
14052 ret = xmlValidateQName(value, 1);
14053 if (ret == 0) {
14054 xmlChar *prefix;
14055
14056 local = xmlSplitQName2(value, &prefix);
14057 if (prefix != NULL) {
14058 xmlNsPtr ns;
14059
14060 ns = xmlSearchNs(node->doc, node, prefix);
14061 if (ns == NULL)
14062 ret = 2;
14063 else {
14064 *nsName = xmlStrdup(ns->href);
14065 *localName = xmlStrdup(local);
14066 }
14067 }
14068 if (local != NULL)
14069 xmlFree(local);
14070 if (prefix != NULL)
14071 xmlFree(prefix);
14072 } else
14073 return (1);
14074 return (ret);
14075}
14076
14077/**
14078 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000014079 * @ctxt: a schema validation context
14080 * @node: the top node.
14081 *
14082 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014083 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000014084 *
14085 * Returns 0 if the element is schemas valid, a positive error code
14086 * number otherwise and -1 in case of internal or API error.
14087 */
14088static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014089xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
14090 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014091{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014092 xmlNodePtr elem;
Daniel Veillard3646d642004-06-02 19:19:14 +000014093 int ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014094 xmlSchemaTypePtr type = NULL;
14095 xmlAttrPtr attr;
14096 xmlChar *attrValue;
14097 int nilled = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000014098
14099 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014100 * This one is called by xmlSchemaValidateElementByWildcardInternal,
14101 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
14102 *
14103 * @ctxt->type will be the element's declaration.
14104 */
Daniel Veillard3646d642004-06-02 19:19:14 +000014105
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014106 if (ctxt == NULL) {
14107 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
14108 "Internal error: xmlSchemaValidateElementByDeclaration, "
14109 "bad arguments.\n",
14110 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014111 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014112 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014113
14114 elem = ctxt->node;
14115
14116 /*
14117 * cvc-elt (3.3.4) : 1
14118 */
14119 if (elemDecl == NULL) {
14120 xmlSchemaVCustomErr(ctxt,
14121 XML_SCHEMAV_CVC_ELT_1,
14122 elem, NULL,
14123 "No matching declaration available", NULL);
14124 return (ctxt->err);
14125 }
14126 /*
14127 * cvc-elt (3.3.4) : 2
14128 */
14129 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
14130 xmlSchemaVCustomErr(ctxt,
14131 XML_SCHEMAV_CVC_ELT_2,
14132 elem, NULL,
14133 "The element declaration is abstract", NULL);
14134 return (ctxt->err);
14135 }
14136
14137 /*
14138 * cvc-elt (3.3.4) : 3
14139 * Handle 'xsi:nil'.
14140 */
14141 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
14142 if (attr != NULL) {
14143 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
14144 ctxt->node = (xmlNodePtr) attr;
14145 ctxt->cur = attr->children;
14146 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
14147 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
14148 BAD_CAST attrValue, 1, 1, 1, 1);
14149 ctxt->node = elem;
14150 ctxt->type = (xmlSchemaTypePtr) elemDecl;
14151 if (ret < 0) {
14152 xmlSchemaVCustomErr(ctxt,
14153 XML_SCHEMAV_INTERNAL,
14154 (xmlNodePtr) attr, NULL,
14155 "Internal error: xmlSchemaValidateElementByDeclaration, "
14156 "validating the attribute 'xsi:nil'", NULL);
14157 if (attrValue != NULL)
14158 xmlFree(attrValue);
14159 return (-1);
14160 }
14161 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
14162 /*
14163 * cvc-elt (3.3.4) : 3.1
14164 */
14165 xmlSchemaVCustomErr(ctxt,
14166 XML_SCHEMAV_CVC_ELT_3_1,
14167 elem, NULL,
14168 "The element is not 'nillable'", NULL);
14169 } else {
14170 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
14171 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
14172 nilled = 1;
14173 ret = 0;
14174 /*
14175 * cvc-elt (3.3.4) : 3.2.1
14176 */
14177 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
14178 xmlSchemaVCustomErr(ctxt,
14179 XML_SCHEMAV_CVC_ELT_3_2_1,
14180 /* XML_SCHEMAS_ERR_NOTEMPTY, */
14181 elem, NULL,
14182 "The 'nilled' element must have no character or element "
14183 "content", NULL);
14184 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
14185 }
14186 /*
14187 * cvc-elt (3.3.4) : 3.2.2
14188 */
14189 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
14190 (elemDecl->value != NULL)) {
14191 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
14192 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
14193 elem, NULL,
14194 "There is a fixed value constraint defined for "
14195 "the 'nilled' element", NULL);
14196 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
14197 }
14198
14199 }
14200 }
14201 if (attrValue != NULL)
14202 xmlFree(attrValue);
14203 }
14204
14205 /*
14206 * cvc-elt (3.3.4) : 4
14207 * Handle 'xsi:type'.
14208 */
14209 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
14210 if (attr != NULL) {
14211 xmlChar *nsName = NULL, *local = NULL;
14212
14213 /*
14214 * TODO: We should report a *warning* that the type was overriden
14215 * by the instance.
14216 */
14217
14218 /*
14219 * cvc-elt (3.3.4) : 4.1
14220 */
14221 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
14222 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
14223 &nsName, &local);
14224 if (ret < 0) {
14225 xmlSchemaVCustomErr(ctxt,
14226 XML_SCHEMAV_INTERNAL,
14227 (xmlNodePtr) attr, NULL,
14228 "Internal error: xmlSchemaValidateElementByDeclaration, "
14229 "validating the attribute 'xsi:type'", NULL);;
14230 FREE_AND_NULL(attrValue)
14231 FREE_AND_NULL(nsName)
14232 FREE_AND_NULL(local)
14233 return (-1);
14234 } else if (ret == 1) {
14235 xmlSchemaVSimpleTypeErr(ctxt,
14236 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
14237 (xmlNodePtr) attr, attrValue,
14238 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
14239 } else if (ret == 2) {
14240 xmlSchemaVCustomErr(ctxt,
14241 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
14242 (xmlNodePtr) attr,
14243 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
14244 "The QName value '%s' has no "
14245 "corresponding namespace declaration in scope",
14246 attrValue);
14247 } else {
14248 /*
14249 * cvc-elt (3.3.4) : 4.2
14250 */
14251 type = xmlSchemaGetType(ctxt->schema, local, nsName);
14252 if (type == NULL) {
14253 xmlChar *strA = NULL;
14254
14255 xmlSchemaVCustomErr(ctxt,
14256 XML_SCHEMAV_CVC_ELT_4_2,
14257 (xmlNodePtr) attr,
14258 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
14259 "The value %s does not resolve to a type "
14260 "definition",
14261 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
14262 FREE_AND_NULL(strA);
14263 } else {
14264 TODO
14265 /*
14266 * TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
14267 */
14268 }
14269 }
14270 FREE_AND_NULL(attrValue)
14271 FREE_AND_NULL(nsName)
14272 FREE_AND_NULL(local)
14273 } else {
14274 type = elemDecl->subtypes;
14275 /* TODO: Change the handling of missing types according to
14276 * the spec.
14277 */
14278 if (type == NULL) {
14279 xmlSchemaVCustomErr(ctxt,
14280 XML_SCHEMAV_INTERNAL,
14281 /* XML_SCHEMAS_ERR_NOTYPE */
14282 elem, NULL,
14283 "The element declaration has no type assigned", NULL);
14284 return (-1);
14285 }
14286 }
14287
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014288 /*
14289 * TODO: Since this should be already checked by the content model automaton,
14290 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
14291 * has been changed to XML_SCHEMAV_INTERNAL.
14292 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014293 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014294 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014295 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014296 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014297 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014298 "Element %s: missing child %s\n",
14299 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014300 }
14301 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014302 }
14303 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014304 /*
14305 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014306 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014307 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014308 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014309 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014310 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014311 "Element %s: missing child %s found %s\n",
14312 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014313 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014314 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014315 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014316 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014317 * URGENT TODO: Look up what to do if the type is not available.
14318 */
14319 if (type != NULL)
14320 xmlSchemaValidateElementByType(ctxt, type);
14321
14322 ctxt->node = elem;
14323 ctxt->type = (xmlSchemaTypePtr) elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014324 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014325}
14326
Daniel Veillard4255d502002-04-16 15:50:10 +000014327/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014328 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000014329 * @ctxt: a schema validation context
14330 * @node: the top node.
14331 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014332 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
14333 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014334 *
14335 * Returns 0 if the element is valid, a positive error code
14336 * number otherwise and -1 in case of an internal error.
14337 */
14338static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014339xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
14340 xmlSchemaWildcardPtr wild,
14341 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014342{
14343 const xmlChar *uri;
14344 int ret = 0;
14345 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014346
14347 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
14348 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14349 if (ret == -1) {
14350 xmlSchemaVCustomErr(ctxt,
14351 XML_SCHEMAV_INTERNAL,
14352 ctxt->node, NULL,
14353 "Internal error: xmlSchemaValidateElement, "
14354 "assembling schema by xsi", NULL);
14355 return (-1);
14356 }
14357 /*
14358 * NOTE: We won't react on schema parser errors here.
14359 * TODO: But a warning would be nice.
14360 */
14361 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014362 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
14363 xmlSchemaElementPtr decl = NULL;
14364
14365 if (node->ns != NULL)
14366 decl = xmlHashLookup3(ctxt->schema->elemDecl,
14367 node->name, node->ns->href, NULL);
14368 else
14369 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
14370 if (decl != NULL) {
14371 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014372 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014373 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014374 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014375 "Internal error: xmlSchemaValidateAnyInternal, "
14376 "validating an element in the context of a wildcard.",
14377 NULL, NULL);
14378 } else if (ret > 0)
14379 return (ret);
14380 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
14381 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014382 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014383 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000014384 return (ctxt->err);
14385 }
14386 }
14387 if (node->children != NULL) {
14388 child = node->children;
14389 do {
14390 if (child->type == XML_ELEMENT_NODE) {
14391 if (child->ns != NULL)
14392 uri = child->ns->href;
14393 else
14394 uri = NULL;
14395 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014396 /* TODO: error code. */
14397 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014398 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014399 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000014400 return (ctxt->err);
14401 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014402 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
14403 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014404 if (ret != 0)
14405 return (ret);
14406 }
14407 child = child->next;
14408 } while (child != NULL);
14409 }
14410 return (0);
14411}
14412
14413/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014414 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000014415 * @ctxt: a schema validation context
14416 *
14417 * Returns 0 if the element is valid, a positive error code
14418 * number otherwise and -1 in case of an internal or API error.
14419 */
14420static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014421xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
14422 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014423{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014424 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
14425 (ctxt->node == NULL)) {
14426 xmlSchemaVCustomErr(ctxt,
14427 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
14428 "Internal error: xmlSchemaValidateElementByWildcard, "
14429 "bad arguments", NULL);
14430 return (-1);
14431 }
14432 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
14433 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014434}
14435
14436/**
William M. Brack2f2a6632004-08-20 23:09:47 +000014437 * xmlSchemaValidateAnyTypeContent:
14438 * @ctxt: a schema validation context
14439 * @node: the current element
14440 *
14441 * This one validates the content of an element of the type
14442 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
14443 * thus elements in the subtree will be validated, if a corresponding
14444 * declaration in the schema exists.
14445 *
14446 * Returns 0 if the element and its subtree is valid, a positive error code
14447 * otherwise and -1 in case of an internal or API error.
14448 */
14449static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014450xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
14451 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014452{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014453 xmlSchemaTypePtr oldtype;
14454 xmlNodePtr top, cur;
14455 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000014456 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014457
14458 if ((type == NULL) || (ctxt->node == NULL))
14459 return (-1);
14460
14461 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000014462 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014463
14464 oldtype = ctxt->type;
14465 top = ctxt->node;
14466 /*
14467 * STREAM: Child nodes are processed.
14468 */
14469 cur = ctxt->node->children;
14470 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014471 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014472 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014473 /*
14474 * The process contents of the wildcard is "lax", thus
14475 * we need to validate the element if a declaration
14476 * exists.
14477 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014478 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000014479 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014480 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014481 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014482 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014483 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014484 ctxt->node = cur;
14485 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
14486 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000014487 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014488 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014489 "Internal error: xmlSchemaValidateAnyTypeContent, "
14490 "validating an element in the context of a wildcard.",
14491 NULL, NULL);
14492 return (ret);
14493 } else if (ret > 0)
14494 return (ret);
14495 skipContent = 1;
14496 }
14497 }
14498 /*
14499 * Browse the full subtree, deep first.
14500 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014501 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014502 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014503 cur = cur->children;
14504 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014505 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014506 cur = cur->next;
14507 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014508 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014509 while (cur != top) {
14510 if (cur->parent != NULL)
14511 cur = cur->parent;
14512 if ((cur != top) && (cur->next != NULL)) {
14513 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000014514 break;
14515 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014516 if (cur->parent == NULL) {
14517 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000014518 break;
14519 }
14520 }
14521 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014522 if (cur == top)
14523 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000014524 } else
14525 break;
14526 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014527 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000014528 return (0);
14529}
14530
14531/**
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014532 * xmlSchemaHasElemOrCharContent:
14533 * @node: the node
14534 *
14535 * Scours the content of the given node for element
14536 * and character nodes.
14537 *
14538 * Returns 1 if an element or character node is found,
14539 * 0 otherwise.
14540 */
14541static int
14542xmlSchemaHasElemOrCharContent(xmlNodePtr node)
14543{
14544 xmlNodePtr cur;
14545
14546 if (node == NULL)
14547 return (0);
14548 cur = node->children;
14549 while (cur != NULL) {
14550 if ((cur->type == XML_ELEMENT_NODE) ||
14551 /*
14552 * TODO: Ask Daniel if these are all character nodes.
14553 */
14554 (cur->type == XML_TEXT_NODE) ||
14555 (cur->type == XML_CDATA_SECTION_NODE) ||
14556 /*
14557 * TODO: How XML_ENTITY_NODEs evaluated?
14558 */
14559 (cur->type == XML_ENTITY_REF_NODE) ||
14560 (cur->type == XML_ENTITY_NODE)) {
14561 return (1);
14562 }
14563 cur = cur->next;
14564 }
14565 return (0);
14566}
14567
14568/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014569 * xmlSchemaValidateComplexType:
14570 * @ctxt: a schema validation context
14571 * @node: the top node.
14572 *
14573 * Validate the content of an element expected to be a complex type type
14574 * xmlschema-1.html#cvc-complex-type
14575 * Validation Rule: Element Locally Valid (Complex Type)
14576 *
14577 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000014578 * number otherwise and -1 in case of internal or API error.
14579 * Note on reported errors: Although it might be nice to report
14580 * the name of the simple/complex type, used to validate the content
14581 * of a node, it is quite unnecessary: for global defined types
14582 * the local name of the element is equal to the NCName of the type,
14583 * for local defined types it makes no sense to output the internal
14584 * computed name of the type. TODO: Instead, one should attach the
14585 * struct of the type involved to the error handler - this allows
14586 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000014587 */
14588static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014589xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
14590 xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014591{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014592 xmlSchemaTypePtr oldtype;
14593 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014594 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000014595 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014596 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014597
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014598 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
14599 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014600
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014601 oldtype = ctxt->type;
14602 ctxt->type = type;
14603 elem = ctxt->node;
14604
14605
14606 /*
14607 * Verify the attributes
14608 */
14609 /*
14610 * TODO: This "attrTop" thing is not needed any more.
14611 */
14612 attrs = ctxt->attr;
14613 attrTop = ctxt->attrTop;
14614 /*
14615 * STREAM: Attribute nodes are processed.
14616 */
14617 xmlSchemaRegisterAttributes(ctxt, elem->properties);
14618 xmlSchemaValidateAttributes(ctxt, elem, type);
14619 if (ctxt->attr != NULL)
14620 xmlSchemaFreeAttributeStates(ctxt->attr);
14621 ctxt->attr = attrs;
14622 ctxt->attrTop = attrTop;
14623
14624 /*
14625 * FIXME TODO: This one creates a regexp even if no content
14626 * model was defined. Somehow ->contModel is always not NULL
14627 * for complex types, even if they are empty.
14628 */
14629 /*
14630 * FIXME TODO URGENT: Move the content model to the
14631 * type definition.
14632 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014633 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014634 case XML_SCHEMA_CONTENT_EMPTY: {
14635 /*
14636 * 1 If the {content type} is empty, then the element information
14637 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000014638 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014639 /*
14640 * TODO: Is the entity stuff correct?
14641 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014642 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014643 xmlSchemaVComplexTypeErr(ctxt,
14644 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014645 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014646 "Character or element content is not allowed, "
14647 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014648 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014649 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014651 case XML_SCHEMA_CONTENT_MIXED:
14652 if ((type->subtypes == NULL) &&
14653 (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))) {
14654 /*
14655 * The type has 'anyType' as its base and no content model
14656 * is defined -> use 'anyType' as the type to validate
14657 * against.
14658 */
14659 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
14660 /* TODO: Handle -1. */
14661 break;
14662 }
14663 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014665 {
14666 xmlRegExecCtxtPtr oldregexp = NULL;
14667
14668
14669 /*
14670 * Content model check initialization.
14671 */
14672 if (type->contModel != NULL) {
14673 oldregexp = ctxt->regexp;
14674 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
14675 (xmlRegExecCallbacks)
14676 xmlSchemaValidateCallback, ctxt);
14677#ifdef DEBUG_AUTOMATA
14678 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
14679#endif
14680 }
14681 /* xmlSchemaValidateElementByType(ctxt, elemDecl->subtypes); */
14682
14683
14684 /*
14685 * STREAM: Children are processed.
14686 */
14687 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014688 while (child != NULL) {
14689 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014690 if (child->ns != NULL)
14691 nsUri = child->ns->href;
14692 else
14693 nsUri = NULL;
14694 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014695 child->name, nsUri, child);
14696 /*
14697 * URGENT TODO: Could we anchor an error report
14698 * here to notify of invalid elements?
14699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014700#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000014701 if (ret < 0)
14702 xmlGenericError(xmlGenericErrorContext,
14703 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000014704 else
14705 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014706 " --> %s\n", child->name);
14707#endif
14708 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
14709 /*
14710 * TODO: Ask Daniel if this are all character nodes.
14711 */
14712 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
14713 (child->type == XML_ENTITY_NODE) ||
14714 (child->type == XML_ENTITY_REF_NODE) ||
14715 (child->type == XML_CDATA_SECTION_NODE))) {
14716 /*
14717 * 2.3 If the {content type} is element-only, then the
14718 * element information item has no character information
14719 * item [children] other than those whose [character
14720 * code] is defined as a white space in [XML 1.0 (Second
14721 * Edition)].
14722 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014723 xmlSchemaVComplexTypeErr(ctxt,
14724 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014725 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014726 "Character content is not allowed, "
14727 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014728 break;
14729 }
14730 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014731 }
14732 /*
14733 * Content model check finalization.
14734 */
14735 if (type->contModel != NULL) {
14736 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
14737#ifdef DEBUG_AUTOMATA
14738 xmlGenericError(xmlGenericErrorContext,
14739 "====> %s : %d\n", elem->name, ret);
14740#endif
14741 if (ret == 0) {
14742 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14743 elem, type, "The element content is not valid", NULL);
14744 } else if (ret < 0) {
14745 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
14746 elem, type, "The element content is not valid", NULL);
14747#ifdef DEBUG_CONTENT
14748 } else {
14749 xmlGenericError(xmlGenericErrorContext,
14750 "Element %s content check succeeded\n",
14751 elem->name);
14752
14753#endif
14754 }
14755 xmlRegFreeExecCtxt(ctxt->regexp);
14756 ctxt->regexp = oldregexp;
14757 }
14758 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014759 break;
14760 case XML_SCHEMA_CONTENT_SIMPLE:
14761 case XML_SCHEMA_CONTENT_BASIC:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000014762 xmlChar *value = NULL;
14763 /*
14764 * We hit a complexType with a simpleContent resolving
14765 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000014766 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014767 /*
14768 * 2.2 If the {content type} is a simple type definition,
14769 * then the element information item has no element
14770 * information item [children], and the ·normalized value·
14771 * of the element information item is ·valid· with respect
14772 * to that simple type definition as defined by String
14773 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014774 */
14775 /*
14776 * STREAM: Children are processed.
14777 */
14778 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014779 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014780 /*
14781 * TODO: Could the entity stuff produce elements
14782 * as well?
14783 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014784 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014785 xmlSchemaVComplexTypeErr(ctxt,
14786 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014787 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014788 "Element content is not allowed, because "
14789 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014790 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14791 break;
14792 }
14793 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014794 }
14795 ctxt->node = elem;
14796 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014797 if (ret == 0) {
14798 /*
14799 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000014800 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014801 /*
14802 * STREAM: Children are processed.
14803 */
14804 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014805 value = NULL;
14806 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014807 value = xmlNodeGetContent(elem);
14808 /*
14809 * URGENT TODO: Should facets for the simple type validation be
14810 * disabled, if the derivation of facets for complex types
14811 * is implemented?
14812 */
14813 /*
14814 * NOTE: This call won't check the correct types of the
14815 * content nodes, since this should be done here.
14816 */
14817 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014818 if (ret > 0) {
14819 /*
14820 * NOTE: Although an error will be reported by
14821 * xmlSchemaValidateSimpleTypeValue, the spec wants
14822 * a specific complex type error to be reported
14823 * additionally.
14824 */
14825 xmlSchemaVComplexTypeErr(ctxt,
14826 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014827 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014828 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014829 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14830 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014831 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014832 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014833 "Element '%s': Error while validating character "
14834 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014835 elem->name, type->name);
14836 if (value != NULL)
14837 xmlFree(value);
14838 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014839 return (-1);
14840 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014841 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014842 if (ret == 0) {
14843 /*
14844 * Apply facets of the complexType. Be sure to pass the
14845 * built-in type to xmlSchemaValidateFacetsInternal.
14846 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014848 * are used, or if the facets, defined by this complex type,
14849 * are to be used only. This here applies both facet sets.
14850 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014851
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014852 ret = xmlSchemaValidateFacetsInternal(ctxt,
14853 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014854 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014855 xmlSchemaVComplexTypeErr(ctxt,
14856 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014857 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000014858 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014859 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
14860 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014861 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014862 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014863 "Element '%s': Error while validating character "
14864 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014865 "apply facets.\n",
14866 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014867 if (value != NULL)
14868 xmlFree(value);
14869 ctxt->type = oldtype;
14870 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014871 }
14872 }
14873 if (value != NULL)
14874 xmlFree(value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014875 break;
14876 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014877 default:
14878 TODO xmlGenericError(xmlGenericErrorContext,
14879 "unimplemented content type %d\n",
14880 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000014881 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014882 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014883 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014884}
14885
14886/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014887 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000014888 * @ctxt: a schema validation context
14889 * @elem: an element
14890 * @type: the list of type declarations
14891 *
14892 * Validate the content of an element against the types.
14893 *
14894 * Returns 0 if the element is schemas valid, a positive error code
14895 * number otherwise and -1 in case of internal or API error.
14896 */
14897static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014898xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
14899 xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014900{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014901 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000014902
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014903 /*
14904 * This one is called by "xmlSchemaValidateElementByDeclaration".
14905 * It will forward to the proper validation
14906 * procedures for the given type.
14907 */
14908 if ((type == NULL) || (ctxt == NULL))
14909 return (-1);
14910
Daniel Veillard4255d502002-04-16 15:50:10 +000014911 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014912 * @elemDecl->subtypes will be of type XML_SCHEMA_TYPE_COMPLEX,
14913 * XML_SCHEMA_TYPE_SIMPLE or XML_SCHEMA_TYPE_BASIC.
14914 */
14915 switch (type->type) {
14916 case XML_SCHEMA_TYPE_COMPLEX:
14917 ret = xmlSchemaValidateElementByComplexType(ctxt, type);
14918 break;
14919 case XML_SCHEMA_TYPE_SIMPLE:
14920 ret = xmlSchemaValidateElementBySimpleType(ctxt, type);
14921 break;
14922 case XML_SCHEMA_TYPE_BASIC:
14923 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
14924 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
14925 else
14926 ret = xmlSchemaValidateElementBySimpleType(ctxt, type);
14927 break;
14928 default:
14929 ret = -1;
14930 break;
14931 }
14932 if (ret == -1)
14933 return (-1);
14934 else
14935 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000014936}
14937
14938
14939/**
14940 * xmlSchemaValidateAttributes:
14941 * @ctxt: a schema validation context
14942 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000014943 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000014944 *
14945 * Validate the attributes of an element.
14946 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000014947 * 1. Existent, invalid attributes are reported in the form
14948 * "prefix:localName".
14949 * Reason: readability - it is easier to find the actual XML
14950 * representation of the attributes QName.
14951 * 2. Missing attributes are reported in the form
14952 * {"URI", "localName"}.
14953 * This is necessary, since the the prefix need not to be declared
14954 * at all, and thus is not computable.
14955 *
Daniel Veillard4255d502002-04-16 15:50:10 +000014956 * Returns 0 if the element is schemas valid, a positive error code
14957 * number otherwise and -1 in case of internal or API error.
14958 */
14959static int
Daniel Veillard3646d642004-06-02 19:19:14 +000014960xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014961{
Daniel Veillard3646d642004-06-02 19:19:14 +000014962 int ret;
14963 xmlAttrPtr attr; /* An attribute on the element. */
Daniel Veillard4255d502002-04-16 15:50:10 +000014964 xmlChar *value;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000014965 const xmlChar *nsURI;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014966 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014967 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000014968 int found;
William M. Brack803812b2004-06-03 02:11:24 +000014969 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014970 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000014971#ifdef DEBUG_ATTR_VALIDATION
14972 int redundant = 0;
14973#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014974
Daniel Veillardc0826a72004-08-10 14:17:33 +000014975 /*
14976 * NOTE: This one uses attr->subtypes to get the type decl. - regardless
14977 * if we have an attribute reference or an attribute declaration.
14978 */
14979 /*
14980 * Allow all attributes if the type is anyType.
14981 */
14982 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
14983 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014984
14985 oldnode = ctxt->node;
14986 if (type != NULL)
14987 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000014988 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000014989 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000014990 attrDecl = attrUse->attr;
14991#ifdef DEBUG_ATTR_VALIDATION
14992 printf("attr use - name: %s\n", xmlSchemaGetOnymousAttrName(attrDecl));
14993 printf("attr use - use: %d\n", attrDecl->occurs);
14994#endif
14995 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
14996
14997 if (curState->decl == attrUse->attr) {
14998#ifdef DEBUG_ATTR_VALIDATION
14999 redundant = 1;
15000#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015001 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015002 attr = curState->attr;
15003#ifdef DEBUG_ATTR_VALIDATION
15004 printf("attr - name: %s\n", attr->name);
15005 if (attr->ns != NULL)
15006 printf("attr - ns: %s\n", attr->ns->href);
15007 else
15008 printf("attr - ns: none\n");
15009#endif
15010 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015011 if (attr == NULL)
15012 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015013 if (attrDecl->ref != NULL) {
15014 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015015 continue;
15016 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000015017 if ((attrDecl->refNs == NULL) ||
15018 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015019 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015020 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015021 continue;
15022 }
15023 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000015024 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015025 continue;
15026 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015027 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015028 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015029 if (attr->ns == NULL) {
15030 /*
William M. Bracke7091952004-05-11 15:09:58 +000015031 * accept an unqualified attribute only if the target
15032 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015033 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015034 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000015035 /*
15036 * This check was removed, since the target namespace
15037 * was evaluated during parsing and already took
15038 * "attributeFormDefault" into account.
15039 */
15040 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015041 continue;
15042 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000015043 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015044 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000015045 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000015046 attr->ns->href))
15047 continue;
15048 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015049 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015050#ifdef DEBUG_ATTR_VALIDATION
15051 printf("found\n");
15052#endif
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000015053 found = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015054
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000015055
Daniel Veillard3646d642004-06-02 19:19:14 +000015056 if (attrDecl->subtypes == NULL) {
15057 curState->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
15058 curState->decl = attrDecl;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015059 xmlSchemaVErr(ctxt, (xmlNodePtr) attr, XML_SCHEMAV_INTERNAL,
William M. Bracke7091952004-05-11 15:09:58 +000015060 "Internal error: attribute %s type not resolved\n",
15061 attr->name, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015062 continue;
15063 }
15064 value = xmlNodeListGetString(elem->doc, attr->children, 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015065 ctxt->node = (xmlNodePtr) attr;
15066 ctxt->cur = attr->children;
15067 /*
15068 * NOTE: This call also checks the content nodes for correct type.
15069 */
15070 ret = xmlSchemaValidateSimpleTypeValue(ctxt, attrDecl->subtypes,
15071 value, 1, 1, 1, 1);
Daniel Veillard3646d642004-06-02 19:19:14 +000015072 if (ret != 0)
15073 curState->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
15074 else
15075 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15076 curState->decl = attrDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015077 if (value != NULL) {
15078 xmlFree(value);
Daniel Veillard3646d642004-06-02 19:19:14 +000015079 }
15080 }
15081 if ((!found) && (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
15082 xmlSchemaAttrStatePtr tmp;
15083
15084#ifdef DEBUG_ATTR_VALIDATION
15085 printf("required attr not found\n");
15086#endif
15087 /*
15088 * Add a new dummy attribute state.
15089 */
15090 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
15091 if (tmp == NULL) {
15092 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015093 ctxt->node = oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000015094 return (-1);
15095 }
15096 tmp->attr = NULL;
15097 tmp->state = XML_SCHEMAS_ATTR_MISSING;
15098 tmp->decl = attrDecl;
15099 tmp->next = NULL;
15100
15101 if (reqAttrStates == NULL) {
15102 reqAttrStates = tmp;
15103 reqAttrStatesTop = tmp;
15104 } else {
15105 reqAttrStatesTop->next = tmp;
15106 reqAttrStatesTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015107 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015108
15109 }
15110 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015111 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015112 /*
15113 * Add required attributes to the attribute states of the context.
15114 */
15115 if (reqAttrStates != NULL) {
15116 if (ctxt->attr == NULL) {
15117 ctxt->attr = reqAttrStates;
15118 } else {
15119 ctxt->attrTop->next = reqAttrStates;
15120 }
15121 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015122 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015123 /*
15124 * Process wildcards.
15125 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015126 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000015127#ifdef DEBUG_ATTR_VALIDATION
15128 xmlSchemaWildcardNsPtr ns;
15129 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015130 if (type->attributeWildcard->processContents ==
15131 XML_SCHEMAS_ANY_LAX)
15132 printf("processContents: lax\n");
15133 else if (type->attributeWildcard->processContents ==
15134 XML_SCHEMAS_ANY_STRICT)
15135 printf("processContents: strict\n");
15136 else
15137 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000015138 if (type->attributeWildcard->any)
15139 printf("type: any\n");
15140 else if (type->attributeWildcard->negNsSet != NULL) {
15141 printf("type: negated\n");
15142 if (type->attributeWildcard->negNsSet->value == NULL)
15143 printf("ns: (absent)\n");
15144 else
15145 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
15146 } else if (type->attributeWildcard->nsSet != NULL) {
15147 printf("type: set\n");
15148 ns = type->attributeWildcard->nsSet;
15149 while (ns != NULL) {
15150 if (ns->value == NULL)
15151 printf("ns: (absent)\n");
15152 else
15153 printf("ns: %s\n", ns->value);
15154 ns = ns->next;
15155 }
15156 } else
15157 printf("empty\n");
15158
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015159
15160#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000015161 curState = ctxt->attr;
15162 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015163 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
15164 if (curState->attr->ns != NULL)
15165 nsURI = curState->attr->ns->href;
15166 else
15167 nsURI = NULL;
15168 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
15169 nsURI)) {
15170 /*
15171 * Handle processContents.
15172 */
15173 if ((type->attributeWildcard->processContents ==
15174 XML_SCHEMAS_ANY_LAX) ||
15175 (type->attributeWildcard->processContents ==
15176 XML_SCHEMAS_ANY_STRICT)) {
15177
15178 attr = curState->attr;
15179 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
15180 attr->name, nsURI);
15181 if (attrDecl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015182 value = xmlNodeListGetString(elem->doc,
15183 attr->children, 1);
15184 ctxt->node = (xmlNodePtr) attr;
15185 ctxt->cur = attr->children;
15186 /*
15187 * NOTE: This call also checks the content nodes
15188 * for correct type.
15189 */
15190 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15191 attrDecl->subtypes, value, 1, 1, 1, 1);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015192 if (ret != 0)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015193 curState->state =
15194 XML_SCHEMAS_ATTR_INVALID_VALUE;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015195 else
15196 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15197 curState->decl = attrDecl;
15198 if (value != NULL) {
15199 xmlFree(value);
15200 }
15201
15202 } else if (type->attributeWildcard->processContents ==
15203 XML_SCHEMAS_ANY_LAX) {
15204 curState->state = XML_SCHEMAS_ATTR_CHECKED;
15205 }
15206 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000015207 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000015208 }
15209 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015210 curState = curState->next;
15211 }
15212 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015213
Daniel Veillardc0826a72004-08-10 14:17:33 +000015214 /*
15215 * Report missing and illegal attributes.
15216 */
15217 if (ctxt->attr != NULL) {
15218 curState = ctxt->attr;
15219 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
15220 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
15221 attr = curState->attr;
15222 if (curState->state == XML_SCHEMAS_ATTR_MISSING)
15223 xmlSchemaVMissingAttrErr(ctxt, elem, curState->decl);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015224 else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
15225 /* TODO: "prohibited" won't ever be touched here!.
15226 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
15227 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015228 /*
15229 * TODO: One might report different error messages
15230 * for the following errors.
15231 */
15232 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015233 xmlSchemaVIllegalAttrErr(ctxt,
15234 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
15235 } else {
15236 xmlSchemaVIllegalAttrErr(ctxt,
15237 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
15238 }
15239 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015240 }
15241 curState = curState->next;
15242 }
15243 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015244#ifdef DEBUG_ATTR_VALIDATION
15245 if (redundant)
15246 xmlGenericError(xmlGenericErrorContext,
15247 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
15248 type->name);
15249#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015250 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015251 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015252}
15253
15254/**
15255 * xmlSchemaValidateElement:
15256 * @ctxt: a schema validation context
15257 * @elem: an element
15258 *
15259 * Validate an element in a tree
15260 *
15261 * Returns 0 if the element is schemas valid, a positive error code
15262 * number otherwise and -1 in case of internal or API error.
15263 */
15264static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015265xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015266{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015267 xmlSchemaElementPtr elemDecl;
Daniel Veillard3646d642004-06-02 19:19:14 +000015268 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000015269
Daniel Veillardc0826a72004-08-10 14:17:33 +000015270 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015271 * This one is called by xmlSchemaValidateDocument and
15272 * xmlSchemaValidateOneElement.
15273 */
15274 /*
15275 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015276 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015277 if (ctxt->options & XML_SCHEMA_VAL_XSI_ASSEMBLE) {
15278 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15279 if (ret == -1) {
15280 xmlSchemaVCustomErr(ctxt,
15281 XML_SCHEMAV_INTERNAL,
15282 ctxt->node, NULL,
15283 "Internal error: xmlSchemaValidateElement, "
15284 "assembling schema by xsi", NULL);
15285 return (-1);
15286 }
15287 /*
15288 * NOTE: We won't react on schema parser errors here.
15289 * TODO: But a warning would be nice.
15290 */
15291 }
15292
15293 if (ctxt->node->ns != NULL)
15294 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, ctxt->node->ns->href);
15295 else
15296 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
15297
Daniel Veillard4255d502002-04-16 15:50:10 +000015298 if (elemDecl == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015299 xmlSchemaVCustomErr(ctxt,
15300 XML_SCHEMAV_CVC_ELT_1,
15301 ctxt->node, NULL,
15302 "No matching global declaration available", NULL);
15303 return (XML_SCHEMAV_CVC_ELT_1);
15304 }
15305
15306 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
15307 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015308 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015309 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15310 "Internal error: xmlSchemaValidateElement, "
15311 "calling validation by declaration", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015312 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015313 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000015314}
15315
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015316
Daniel Veillard4255d502002-04-16 15:50:10 +000015317/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015318 * xmlSchemaValidateOneElement:
15319 * @ctxt: a schema validation context
15320 * @elem: an element node
15321 *
15322 * Validate a branch of a tree, starting with the given @elem.
15323 *
15324 * Returns 0 if the element and its subtree is valid, a positive error
15325 * code number otherwise and -1 in case of an internal or API error.
15326 */
15327int
15328xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
15329{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015330 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015331 return (-1);
15332
15333 ctxt->doc = elem->doc;
15334 ctxt->err = 0;
15335 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015336 ctxt->node = elem;
15337 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000015338}
15339
15340/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015341 * xmlSchemaValidateDocument:
15342 * @ctxt: a schema validation context
15343 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015344 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000015345 *
15346 * Validate a document tree in memory.
15347 *
15348 * Returns 0 if the document is schemas valid, a positive error code
15349 * number otherwise and -1 in case of internal or API error.
15350 */
15351static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015352xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
15353{
Daniel Veillard4255d502002-04-16 15:50:10 +000015354 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015355
Daniel Veillard4255d502002-04-16 15:50:10 +000015356 root = xmlDocGetRootElement(doc);
15357 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015358 xmlSchemaVCustomErr(ctxt,
15359 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
15360 (xmlNodePtr) doc, NULL,
15361 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015362 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015363 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015364 /*
15365 * Okay, start the recursive validation
15366 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015367 ctxt->node = root;
15368 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015369
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015370 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015371}
15372
15373/************************************************************************
15374 * *
15375 * SAX Validation code *
15376 * *
15377 ************************************************************************/
15378
15379/************************************************************************
15380 * *
15381 * Validation interfaces *
15382 * *
15383 ************************************************************************/
15384
15385/**
15386 * xmlSchemaNewValidCtxt:
15387 * @schema: a precompiled XML Schemas
15388 *
15389 * Create an XML Schemas validation context based on the given schema
15390 *
15391 * Returns the validation context or NULL in case of error
15392 */
15393xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015394xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
15395{
Daniel Veillard4255d502002-04-16 15:50:10 +000015396 xmlSchemaValidCtxtPtr ret;
15397
15398 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
15399 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015400 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015401 return (NULL);
15402 }
15403 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015404 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000015405 ret->attrTop = NULL;
15406 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015407 return (ret);
15408}
15409
15410/**
15411 * xmlSchemaFreeValidCtxt:
15412 * @ctxt: the schema validation context
15413 *
15414 * Free the resources associated to the schema validation context
15415 */
15416void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015417xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
15418{
Daniel Veillard4255d502002-04-16 15:50:10 +000015419 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015420 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015421 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000015422 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000015423 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015424 xmlSchemaFreeValue(ctxt->value);
Daniel Veillard4255d502002-04-16 15:50:10 +000015425 xmlFree(ctxt);
15426}
15427
15428/**
15429 * xmlSchemaSetValidErrors:
15430 * @ctxt: a schema validation context
15431 * @err: the error function
15432 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000015433 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000015434 *
William M. Brack2f2a6632004-08-20 23:09:47 +000015435 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000015436 */
15437void
15438xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015439 xmlSchemaValidityErrorFunc err,
15440 xmlSchemaValidityWarningFunc warn, void *ctx)
15441{
Daniel Veillard4255d502002-04-16 15:50:10 +000015442 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015443 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015444 ctxt->error = err;
15445 ctxt->warning = warn;
15446 ctxt->userData = ctx;
15447}
15448
15449/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015450 * xmlSchemaGetValidErrors:
15451 * @ctxt: a XML-Schema validation context
15452 * @err: the error function result
15453 * @warn: the warning function result
15454 * @ctx: the functions context result
15455 *
15456 * Get the error and warning callback informations
15457 *
15458 * Returns -1 in case of error and 0 otherwise
15459 */
15460int
15461xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
15462 xmlSchemaValidityErrorFunc * err,
15463 xmlSchemaValidityWarningFunc * warn, void **ctx)
15464{
15465 if (ctxt == NULL)
15466 return (-1);
15467 if (err != NULL)
15468 *err = ctxt->error;
15469 if (warn != NULL)
15470 *warn = ctxt->warning;
15471 if (ctx != NULL)
15472 *ctx = ctxt->userData;
15473 return (0);
15474}
15475
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015476#if 0 /* Will be enabled if it is clear what options are needed. */
15477/**
15478 * xmlSchemaValidCtxtSetOptions:
15479 * @ctxt: a schema validation context
15480 * @options: a combination of xmlSchemaValidOption
15481 *
15482 * Sets the options to be used during the validation.
15483 *
15484 * Returns 0 in case of success, -1 in case of an
15485 * API error.
15486 */
15487static int
15488xmlSchemaValidCtxtSetOptions(xmlSchemaValidCtxtPtr ctxt,
15489 int options)
15490
15491{
15492 int i;
15493
15494 if (ctxt == NULL)
15495 return (-1);
15496 /*
15497 * WARNING: Change the start value if adding to the
15498 * xmlSchemaValidOption.
15499 */
15500 for (i = 1; i <= (int) sizeof(int) * 8; i++) {
15501 if (options & 1<<i) {
15502 return (-1);
15503 }
15504 }
15505 ctxt->options = options;
15506 return (0);
15507}
15508
15509/**
15510 * xmlSchemaValidCtxtGetOptions:
15511 * @ctxt: a schema validation context
15512 *
15513 * Returns the option combination of the validation context.
15514 */
15515static int
15516xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
15517
15518{
15519 if (ctxt == NULL)
15520 return (-1);
15521 else
15522 return (ctxt->options);
15523}
15524#endif
15525
Daniel Veillard259f0df2004-08-18 09:13:18 +000015526/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015527 * xmlSchemaValidateDoc:
15528 * @ctxt: a schema validation context
15529 * @doc: a parsed document tree
15530 *
15531 * Validate a document tree in memory.
15532 *
15533 * Returns 0 if the document is schemas valid, a positive error code
15534 * number otherwise and -1 in case of internal or API error.
15535 */
15536int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015537xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
15538{
Daniel Veillard4255d502002-04-16 15:50:10 +000015539 int ret;
15540
15541 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015542 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015543
15544 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000015545 ctxt->err = 0;
15546 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015547
Daniel Veillard4255d502002-04-16 15:50:10 +000015548 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015549 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000015550}
15551
15552/**
15553 * xmlSchemaValidateStream:
15554 * @ctxt: a schema validation context
15555 * @input: the input to use for reading the data
15556 * @enc: an optional encoding information
15557 * @sax: a SAX handler for the resulting events
15558 * @user_data: the context to provide to the SAX handler.
15559 *
15560 * Validate a document tree in memory.
15561 *
15562 * Returns 0 if the document is schemas valid, a positive error code
15563 * number otherwise and -1 in case of internal or API error.
15564 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015565int
Daniel Veillard4255d502002-04-16 15:50:10 +000015566xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015567 xmlParserInputBufferPtr input, xmlCharEncoding enc,
15568 xmlSAXHandlerPtr sax, void *user_data)
15569{
Daniel Veillard4255d502002-04-16 15:50:10 +000015570 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015571 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015572 ctxt->input = input;
15573 ctxt->enc = enc;
15574 ctxt->sax = sax;
15575 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015576 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015577}
15578
15579#endif /* LIBXML_SCHEMAS_ENABLED */