blob: b664c9bfe111c303b8f15d4d282ab0d47ba65e8a [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
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000094#define IS_ANYTYPE(item) \
95 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
96 (item->builtInType == XML_SCHEMAS_ANYTYPE))
97
98#define IS_COMPLEX_TYPE(item) \
99 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
100 (item->builtInType == XML_SCHEMAS_ANYTYPE))
101
102#define IS_SIMPLE_TYPE(item) \
103 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
104 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
105 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
108#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
109#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
110
Daniel Veillard4255d502002-04-16 15:50:10 +0000111#define XML_SCHEMAS_PARSE_ERROR 1
112
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000113#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
114
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000115
116/*
117* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
118* allow to assemble schemata with
119* the same target namespace from
120* different sources; otherwise, the first
121* encountered schema with a specific target
122* namespace will be used only *
123
124*
125* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
126* locate schemata to be imported
127* using the namespace name; otherwise
128* the location URI will be used */
129
130/*
131* xmlSchemaParserOption:
132*
133* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000134*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000135typedef enum {
136 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000137 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000139 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000140} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000141*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000142
143/*
144XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000145 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
146 int options);
147XMLPUBFUN int XMLCALL
148 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
149
150*/
151
152typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
153typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
154struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000155 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 int nbItems; /* used for dynamic addition of schemata */
157 int sizeItems; /* used for dynamic addition of schemata */
158};
159
Daniel Veillard4255d502002-04-16 15:50:10 +0000160struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000161 void *userData; /* user specific data block */
162 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
163 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000164 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000166 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000167
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000168 xmlSchemaPtr topschema; /* The main schema */
169 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
170
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000171 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000173 int counter;
174
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000175 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000177 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000179 const char *buffer;
180 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000181
Daniel Veillard4255d502002-04-16 15:50:10 +0000182 /*
183 * Used to build complex element content models
184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000185 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 xmlAutomataStatePtr start;
187 xmlAutomataStatePtr end;
188 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000189
190 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000191 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000192 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
193 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194 xmlSchemaAssemblePtr assemble;
195 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000196 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197};
198
199
200#define XML_SCHEMAS_ATTR_UNKNOWN 1
201#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000202#define XML_SCHEMAS_ATTR_PROHIBITED 3
203#define XML_SCHEMAS_ATTR_MISSING 4
204#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
205#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000206#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
207#define XML_SCHEMAS_ATTR_DEFAULT 8
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;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000216 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000217};
218
219/**
220 * xmlSchemaValidCtxt:
221 *
222 * A Schemas validation context
223 */
224
225struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000229 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000231 xmlSchemaPtr schema; /* The schema in use */
232 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000234 xmlCharEncoding enc;
235 xmlSAXHandlerPtr sax;
236 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 xmlDocPtr myDoc;
239 int err;
240 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000241
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000242 xmlNodePtr node;
243 xmlNodePtr cur;
244 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000246 xmlRegExecCtxtPtr regexp;
247 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248
Daniel Veillard3646d642004-06-02 19:19:14 +0000249 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000251 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000252 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000254 xmlNodePtr validationRoot;
255 xmlSchemaParserCtxtPtr pctxt;
256 int xsiAssemble;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257};
258
Daniel Veillard1d913862003-11-21 00:28:39 +0000259/*
260 * These are the entries in the schemas importSchemas hash table
261 */
262typedef struct _xmlSchemaImport xmlSchemaImport;
263typedef xmlSchemaImport *xmlSchemaImportPtr;
264struct _xmlSchemaImport {
265 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000266 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000267 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000268 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000269};
Daniel Veillard4255d502002-04-16 15:50:10 +0000270
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000271/*
272 * These are the entries associated to includes in a schemas
273 */
274typedef struct _xmlSchemaInclude xmlSchemaInclude;
275typedef xmlSchemaInclude *xmlSchemaIncludePtr;
276struct _xmlSchemaInclude {
277 xmlSchemaIncludePtr next;
278
279 const xmlChar *schemaLocation;
280 xmlDocPtr doc;
281};
282
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000283typedef struct _xmlSchemaParticle xmlSchemaParticle;
284typedef xmlSchemaParticle *xmlSchemaParticlePtr;
285struct _xmlSchemaParticle {
286 xmlSchemaTypeType type;
287 xmlSchemaParticlePtr next; /* the next particle if in a list */
288 int minOccurs;
289 int maxOccurs;
290 xmlSchemaTypePtr term;
291};
292
293
294typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
295typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
296struct _xmlSchemaModelGroup {
297 xmlSchemaTypeType type;
298 int compositor; /* one of all, choice or sequence */
299 xmlSchemaParticlePtr particles; /* list of particles */
300 xmlSchemaAnnotPtr annot;
301};
302
303typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
304typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
305struct _xmlSchemaModelGroupDef {
306 xmlSchemaTypeType type;
307 const xmlChar *name;
308 const xmlChar *targetNamespace;
309 xmlSchemaModelGroupPtr modelGroup;
310 xmlSchemaAnnotPtr annot;
311};
312
Daniel Veillard4255d502002-04-16 15:50:10 +0000313/************************************************************************
314 * *
315 * Some predeclarations *
316 * *
317 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000318
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000319static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
320 xmlSchemaPtr schema,
321 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000322static void
323xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
324 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
325static const char *
326xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
327static int
328xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000329 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000330 const xmlChar *value,
331 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000332 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000333 int normalize,
334 int checkNodes);
335static int
336xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
337 xmlSchemaElementPtr elemDecl);
338static int
339xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
340 xmlSchemaTypePtr type);
341static int
342xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000343static int
344xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
345 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000346static void
347xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
348 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000349
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000350/************************************************************************
351 * *
352 * Datatype error handlers *
353 * *
354 ************************************************************************/
355
356/**
357 * xmlSchemaPErrMemory:
358 * @node: a context node
359 * @extra: extra informations
360 *
361 * Handle an out of memory condition
362 */
363static void
364xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
365 const char *extra, xmlNodePtr node)
366{
367 if (ctxt != NULL)
368 ctxt->nberrors++;
369 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
370 extra);
371}
372
373/**
374 * xmlSchemaPErr:
375 * @ctxt: the parsing context
376 * @node: the context node
377 * @error: the error code
378 * @msg: the error message
379 * @str1: extra data
380 * @str2: extra data
381 *
382 * Handle a parser error
383 */
384static void
385xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
386 const char *msg, const xmlChar * str1, const xmlChar * str2)
387{
388 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000389 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 void *data = NULL;
391
392 if (ctxt != NULL) {
393 ctxt->nberrors++;
394 channel = ctxt->error;
395 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000396 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000397 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000398 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000399 error, XML_ERR_ERROR, NULL, 0,
400 (const char *) str1, (const char *) str2, NULL, 0, 0,
401 msg, str1, str2);
402}
403
404/**
405 * xmlSchemaPErr2:
406 * @ctxt: the parsing context
407 * @node: the context node
408 * @node: the current child
409 * @error: the error code
410 * @msg: the error message
411 * @str1: extra data
412 * @str2: extra data
413 *
414 * Handle a parser error
415 */
416static void
417xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
418 xmlNodePtr child, int error,
419 const char *msg, const xmlChar * str1, const xmlChar * str2)
420{
421 if (child != NULL)
422 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
423 else
424 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
425}
426
Daniel Veillard01fa6152004-06-29 17:04:39 +0000427
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000429 * xmlSchemaPErrExt:
430 * @ctxt: the parsing context
431 * @node: the context node
432 * @error: the error code
433 * @strData1: extra data
434 * @strData2: extra data
435 * @strData3: extra data
436 * @msg: the message
437 * @str1: extra parameter for the message display
438 * @str2: extra parameter for the message display
439 * @str3: extra parameter for the message display
440 * @str4: extra parameter for the message display
441 * @str5: extra parameter for the message display
442 *
443 * Handle a parser error
444 */
445static void
446xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
447 const xmlChar * strData1, const xmlChar * strData2,
448 const xmlChar * strData3, const char *msg, const xmlChar * str1,
449 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
450 const xmlChar * str5)
451{
452
453 xmlGenericErrorFunc channel = NULL;
454 xmlStructuredErrorFunc schannel = NULL;
455 void *data = NULL;
456
457 if (ctxt != NULL) {
458 ctxt->nberrors++;
459 channel = ctxt->error;
460 data = ctxt->userData;
461 schannel = ctxt->serror;
462 }
463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
464 error, XML_ERR_ERROR, NULL, 0,
465 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000466 (const char *) strData3, 0, 0, msg, str1, str2,
467 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000468}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000469
Daniel Veillard3646d642004-06-02 19:19:14 +0000470
471/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000472 * xmlSchemaVTypeErrMemory:
473 * @node: a context node
474 * @extra: extra informations
475 *
476 * Handle an out of memory condition
477 */
478static void
479xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
480 const char *extra, xmlNodePtr node)
481{
482 if (ctxt != NULL) {
483 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000484 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000485 }
486 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
487 extra);
488}
489
490/**
491 * xmlSchemaVErr3:
492 * @ctxt: the validation context
493 * @node: the context node
494 * @error: the error code
495 * @msg: the error message
496 * @str1: extra data
497 * @str2: extra data
498 * @str3: extra data
499 *
500 * Handle a validation error
501 */
502static void
503xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
504 const char *msg, const xmlChar *str1, const xmlChar *str2,
505 const xmlChar *str3)
506{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000507 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000508 xmlGenericErrorFunc channel = NULL;
509 void *data = NULL;
510
511 if (ctxt != NULL) {
512 ctxt->nberrors++;
513 ctxt->err = error;
514 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000515 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000516 data = ctxt->userData;
517 }
518 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000519 /* Removed, since the old schema error codes have been
520 * substituted for the global error codes.
521 *
522 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
523 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000524 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000525 error, XML_ERR_ERROR, NULL, 0,
526 (const char *) str1, (const char *) str2,
527 (const char *) str3, 0, 0,
528 msg, str1, str2, str3);
529}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000530
531/**
532 * xmlSchemaVErrExt:
533 * @ctxt: the validation context
534 * @node: the context node
535 * @error: the error code
536 * @msg: the message
537 * @str1: extra parameter for the message display
538 * @str2: extra parameter for the message display
539 * @str3: extra parameter for the message display
540 * @str4: extra parameter for the message display
541 * @str5: extra parameter for the message display
542 *
543 * Handle a validation error
544 */
545static void
546xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
547 const char *msg, const xmlChar * str1,
548 const xmlChar * str2, const xmlChar * str3,
549 const xmlChar * str4, const xmlChar * str5)
550{
551 xmlStructuredErrorFunc schannel = NULL;
552 xmlGenericErrorFunc channel = NULL;
553 void *data = NULL;
554
555 if (ctxt != NULL) {
556 ctxt->nberrors++;
557 ctxt->err = error;
558 channel = ctxt->error;
559 schannel = ctxt->serror;
560 data = ctxt->userData;
561 }
562 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000563 /* Removed, since the old schema error codes have been
564 * substituted for the global error codes.
565 *
566 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
567 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000568 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
569 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
570 msg, str1, str2, str3, str4, str5);
571}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572/**
573 * xmlSchemaVErr:
574 * @ctxt: the validation context
575 * @node: the context node
576 * @error: the error code
577 * @msg: the error message
578 * @str1: extra data
579 * @str2: extra data
580 *
581 * Handle a validation error
582 */
583static void
584xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
585 const char *msg, const xmlChar * str1, const xmlChar * str2)
586{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000587 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000588 xmlGenericErrorFunc channel = NULL;
589 void *data = NULL;
590
591 if (ctxt != NULL) {
592 ctxt->nberrors++;
593 ctxt->err = error;
594 channel = ctxt->error;
595 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000596 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 }
598 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000599 /* Removed, since the old schema error codes have been
600 * substituted for the global error codes.
601 *
602 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
603 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000604 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000605 error, XML_ERR_ERROR, NULL, 0,
606 (const char *) str1, (const char *) str2, NULL, 0, 0,
607 msg, str1, str2);
608}
Daniel Veillard4255d502002-04-16 15:50:10 +0000609
Daniel Veillardc0826a72004-08-10 14:17:33 +0000610/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000611 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000612 * @attr: the attribute declaration/use
613 *
614 * Returns the name of the attribute; if the attribute
615 * is a reference, the name of the referenced global type will be returned.
616 */
617static const xmlChar *
618xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
619{
620 if (attr->ref != NULL)
621 return(attr->ref);
622 else
623 return(attr->name);
624}
625
626/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000627 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000628 * @type: the type (element or attribute)
629 *
630 * Returns the target namespace URI of the type; if the type is a reference,
631 * the target namespace of the referenced type will be returned.
632 */
633static const xmlChar *
634xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
635{
636 if (attr->ref != NULL)
637 return (attr->refNs);
638 else
639 return(attr->targetNamespace);
640}
641
642/**
643 * xmlSchemaFormatNsUriLocal:
644 * @buf: the string buffer
645 * @uri: the namespace URI
646 * @local: the local name
647 *
648 * Returns a representation of the given URI used
649 * for error reports.
650 *
651 * Returns an empty string, if @ns is NULL, a formatted
652 * string otherwise.
653 */
654static const xmlChar*
655xmlSchemaFormatNsUriLocal(xmlChar **buf,
656 const xmlChar *uri, const xmlChar *local)
657{
658 if (*buf != NULL)
659 xmlFree(*buf);
660 if (uri == NULL) {
661 *buf = xmlStrdup(BAD_CAST "{'");
662 *buf = xmlStrcat(*buf, local);
663 } else {
664 *buf = xmlStrdup(BAD_CAST "{'");
665 *buf = xmlStrcat(*buf, uri);
666 *buf = xmlStrcat(*buf, BAD_CAST "', '");
667 *buf = xmlStrcat(*buf, local);
668 }
669 *buf = xmlStrcat(*buf, BAD_CAST "'}");
670 return ((const xmlChar *) *buf);
671}
672
673/**
674 * xmlSchemaFormatNsPrefixLocal:
675 * @buf: the string buffer
676 * @ns: the namespace
677 * @local: the local name
678 *
679 * Returns a representation of the given URI used
680 * for error reports.
681 *
682 * Returns an empty string, if @ns is NULL, a formatted
683 * string otherwise.
684 */
685static const xmlChar*
686xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
687 xmlNsPtr ns, const xmlChar *local)
688{
689 if (*buf != NULL) {
690 xmlFree(*buf);
691 *buf = NULL;
692 }
693 if ((ns == NULL) || (ns->prefix == NULL))
694 return(local);
695 else {
696 *buf = xmlStrdup(ns->prefix);
697 *buf = xmlStrcat(*buf, BAD_CAST ":");
698 *buf = xmlStrcat(*buf, local);
699 }
700 return ((const xmlChar *) *buf);
701}
702
703/**
704 * xmlSchemaFormatItemForReport:
705 * @buf: the string buffer
706 * @itemDes: the designation of the item
707 * @itemName: the name of the item
708 * @item: the item as an object
709 * @itemNode: the node of the item
710 * @local: the local name
711 * @parsing: if the function is used during the parse
712 *
713 * Returns a representation of the given item used
714 * for error reports.
715 *
716 * The following order is used to build the resulting
717 * designation if the arguments are not NULL:
718 * 1a. If itemDes not NULL -> itemDes
719 * 1b. If (itemDes not NULL) and (itemName not NULL)
720 * -> itemDes + itemName
721 * 2. If the preceding was NULL and (item not NULL) -> item
722 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
723 *
724 * If the itemNode is an attribute node, the name of the attribute
725 * will be appended to the result.
726 *
727 * Returns the formatted string and sets @buf to the resulting value.
728 */
729static xmlChar*
730xmlSchemaFormatItemForReport(xmlChar **buf,
731 const xmlChar *itemDes,
732 xmlSchemaTypePtr item,
733 xmlNodePtr itemNode,
734 int parsing)
735{
736 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000737 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000738
739 if (*buf != NULL) {
740 xmlFree(*buf);
741 *buf = NULL;
742 }
743
William M. Brack2f2a6632004-08-20 23:09:47 +0000744 if (itemDes != NULL) {
745 *buf = xmlStrdup(itemDes);
746 } else if (item != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000747 if (item->type == XML_SCHEMA_TYPE_BASIC) {
748 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
749 *buf = xmlStrdup(BAD_CAST "'anyType'");
750 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
751 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
752 else {
753 /* *buf = xmlStrdup(BAD_CAST "bi "); */
754 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
755 *buf = xmlStrdup(BAD_CAST "'");
756 *buf = xmlStrcat(*buf, item->name);
757 *buf = xmlStrcat(*buf, BAD_CAST "'");
758 }
759 } else if (item->type == XML_SCHEMA_TYPE_SIMPLE) {
760 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
761 *buf = xmlStrdup(xmlSchemaElemDesST);
762 *buf = xmlStrcat(*buf, BAD_CAST " '");
763 *buf = xmlStrcat(*buf, item->name);
764 *buf = xmlStrcat(*buf, BAD_CAST "'");
765 } else {
766 *buf = xmlStrdup(xmlSchemaElemDesST);
767 *buf = xmlStrcat(*buf, BAD_CAST " local");
768 }
769 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
770 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
771 *buf = xmlStrdup(xmlSchemaElemDesCT);
772 *buf = xmlStrcat(*buf, BAD_CAST " '");
773 *buf = xmlStrcat(*buf, item->name);
774 *buf = xmlStrcat(*buf, BAD_CAST "'");
775 } else {
776 *buf = xmlStrdup(xmlSchemaElemDesCT);
777 *buf = xmlStrcat(*buf, BAD_CAST " local");
778 }
779 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
780 xmlSchemaAttributePtr attr;
781
782 attr = (xmlSchemaAttributePtr) item;
783 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
784 (attr->ref == NULL)) {
785 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
786 *buf = xmlStrcat(*buf, BAD_CAST " '");
787 *buf = xmlStrcat(*buf, attr->name);
788 *buf = xmlStrcat(*buf, BAD_CAST "'");
789 } else {
790 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
791 *buf = xmlStrcat(*buf, BAD_CAST " '");
792 *buf = xmlStrcat(*buf, attr->refPrefix);
793 *buf = xmlStrcat(*buf, BAD_CAST ":");
794 *buf = xmlStrcat(*buf, attr->ref);
795 *buf = xmlStrcat(*buf, BAD_CAST "'");
796 }
797 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
798 xmlSchemaElementPtr elem;
799
800 elem = (xmlSchemaElementPtr) item;
801 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
802 (elem->ref == NULL)) {
803 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
804 *buf = xmlStrcat(*buf, BAD_CAST " '");
805 *buf = xmlStrcat(*buf, elem->name);
806 *buf = xmlStrcat(*buf, BAD_CAST "'");
807 } else {
808 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
809 *buf = xmlStrcat(*buf, BAD_CAST " '");
810 *buf = xmlStrcat(*buf, elem->refPrefix);
811 *buf = xmlStrcat(*buf, BAD_CAST ":");
812 *buf = xmlStrcat(*buf, elem->ref);
813 *buf = xmlStrcat(*buf, BAD_CAST "'");
814 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000815 } else
816 named = 0;
817 } else
818 named = 0;
819
820 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000821 xmlNodePtr elem;
822
823 if (itemNode->type == XML_ATTRIBUTE_NODE)
824 elem = itemNode->parent;
825 else
826 elem = itemNode;
827 *buf = xmlStrdup(BAD_CAST "Element '");
828 if (parsing)
829 *buf = xmlStrcat(*buf, elem->name);
830 else
831 *buf = xmlStrcat(*buf,
832 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
833 *buf = xmlStrcat(*buf, BAD_CAST "'");
834 }
835 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
836 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
837 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
838 itemNode->ns, itemNode->name));
839 *buf = xmlStrcat(*buf, BAD_CAST "'");
840 }
841 FREE_AND_NULL(str);
842
843 return (*buf);
844}
845
846/**
847 * xmlSchemaPFormatItemDes:
848 * @buf: the string buffer
849 * @item: the item as a schema object
850 * @itemNode: the item as a node
851 *
852 * If the pointer to @buf is not NULL and @but holds no value,
853 * the value is set to a item designation using
854 * xmlSchemaFormatItemForReport. This one avoids adding
855 * an attribute designation postfix.
856 *
857 * Returns a string of all enumeration elements.
858 */
859static void
860xmlSchemaPRequestItemDes(xmlChar **buf,
861 xmlSchemaTypePtr item,
862 xmlNodePtr itemNode)
863{
864 if ((buf == 0) || (*buf != NULL))
865 return;
866 if (itemNode->type == XML_ATTRIBUTE_NODE)
867 itemNode = itemNode->parent;
868 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
869}
870
871/**
872 * xmlSchemaFormatFacetEnumSet:
873 * @buf: the string buffer
874 * @type: the type holding the enumeration facets
875 *
876 * Builds a string consisting of all enumeration elements.
877 *
878 * Returns a string of all enumeration elements.
879 */
880static const xmlChar *
881xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
882{
883 xmlSchemaFacetLinkPtr link;
884
885 if (*buf != NULL)
886 xmlFree(*buf);
887 *buf = NULL;
888 for (link = type->facetSet; link != NULL; link = link->next) {
889 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
890 if (*buf == NULL) {
891 *buf = xmlStrdup(BAD_CAST "'");
892 *buf = xmlStrcat(*buf, link->facet->value);
893 *buf = xmlStrcat(*buf, BAD_CAST "'");
894 } else {
895 *buf = xmlStrcat(*buf, BAD_CAST ", '");
896 *buf = xmlStrcat(*buf, link->facet->value);
897 *buf = xmlStrcat(*buf, BAD_CAST "'");
898 }
899 }
900 }
901 return ((const xmlChar *) *buf);
902}
903
904/**
905 * xmlSchemaVFacetErr:
906 * @ctxt: the schema validation context
907 * @error: the error code
908 * @node: the node to be validated
909 * @value: the value of the node
910 * @type: the type holding the facet
911 * @facet: the facet
912 * @message: the error message of NULL
913 * @str1: extra data
914 * @str2: extra data
915 * @str3: extra data
916 *
917 * Reports a facet validation error.
918 * TODO: Should this report the value of an element as well?
919 */
920static void
921xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
922 xmlParserErrors error,
923 xmlNodePtr node,
924 const xmlChar *value,
925 unsigned long length,
926 xmlSchemaTypePtr type,
927 xmlSchemaFacetPtr facet,
928 const char *message,
929 const xmlChar *str1,
930 const xmlChar *str2,
931 const xmlChar *str3)
932{
933 xmlChar *str = NULL, *msg = NULL;
934 xmlSchemaTypeType facetType;
935
936 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
937 msg = xmlStrcat(msg, BAD_CAST " [");
938 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
939 msg = xmlStrcat(msg, BAD_CAST ", facet '");
940 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
941 facetType = XML_SCHEMA_FACET_ENUMERATION;
942 /*
943 * If enumerations are validated, one must not expect the
944 * facet to be given.
945 */
946 } else
947 facetType = facet->type;
948 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
949 msg = xmlStrcat(msg, BAD_CAST "']: ");
950 if (message == NULL) {
951 /*
952 * Use a default message.
953 */
954 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
955 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
956 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
957
958 char len[25], actLen[25];
959
960 /* FIXME, TODO: What is the max expected string length of the
961 * this value?
962 */
963 if (node->type == XML_ATTRIBUTE_NODE)
964 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
965 else
966 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
967
968 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
969 snprintf(actLen, 24, "%lu", length);
970
971 if (facetType == XML_SCHEMA_FACET_LENGTH)
972 msg = xmlStrcat(msg,
973 BAD_CAST "this differs from the allowed length of '%s'.\n");
974 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
975 msg = xmlStrcat(msg,
976 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
977 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
978 msg = xmlStrcat(msg,
979 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
980
981 if (node->type == XML_ATTRIBUTE_NODE)
982 xmlSchemaVErrExt(ctxt, node, error,
983 (const char *) msg,
984 value, (const xmlChar *) actLen, (const xmlChar *) len,
985 NULL, NULL);
986 else
987 xmlSchemaVErr(ctxt, node, error,
988 (const char *) msg,
989 (const xmlChar *) actLen, (const xmlChar *) len);
990
991 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
992 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
993 "of the set {%s}.\n");
994 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
995 xmlSchemaFormatFacetEnumSet(&str, type));
996 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
997 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
998 "by the pattern '%s'.\n");
999 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1000 facet->value);
1001 } else if (node->type == XML_ATTRIBUTE_NODE) {
1002 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1004 } else {
1005 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1006 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1007 }
1008 } else {
1009 msg = xmlStrcat(msg, (const xmlChar *) message);
1010 msg = xmlStrcat(msg, BAD_CAST ".\n");
1011 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1012 }
1013 FREE_AND_NULL(str)
1014 xmlFree(msg);
1015}
1016
1017/**
1018 * xmlSchemaVSimpleTypeErr:
1019 * @ctxt: the schema validation context
1020 * @error: the error code
1021 * @type: the type used for validation
1022 * @node: the node containing the validated value
1023 * @value: the validated value
1024 *
1025 * Reports a simple type validation error.
1026 * TODO: Should this report the value of an element as well?
1027 */
1028static void
1029xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1030 xmlParserErrors error,
1031 xmlNodePtr node,
1032 const xmlChar *value,
1033 xmlSchemaTypePtr type)
1034{
1035 xmlChar *str = NULL, *msg = NULL;
1036
1037 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1038 msg = xmlStrcat(msg, BAD_CAST " [");
1039 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1040 if (node->type == XML_ATTRIBUTE_NODE) {
1041 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1042 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1043 } else {
1044 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1045 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1046 }
1047 FREE_AND_NULL(str)
1048 xmlFree(msg);
1049}
1050
1051/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001052 * xmlSchemaVComplexTypeErr:
1053 * @ctxt: the schema validation context
1054 * @error: the error code
1055 * @node: the node containing the validated value
1056 * @type: the complex type used for validation
1057 * @message: the error message
1058 *
1059 * Reports a complex type validation error.
1060 */
1061static void
1062xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1063 xmlParserErrors error,
1064 xmlNodePtr node,
1065 xmlSchemaTypePtr type,
1066 const char *message)
1067{
1068 xmlChar *str = NULL, *msg = NULL;
1069
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001070 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1071 if (type != NULL) {
1072 msg = xmlStrcat(msg, BAD_CAST " [");
1073 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1074 msg = xmlStrcat(msg, BAD_CAST "]");
1075 }
1076 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
William M. Brack2f2a6632004-08-20 23:09:47 +00001077 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1078 (const xmlChar *) message, NULL);
1079 FREE_AND_NULL(str)
1080 xmlFree(msg);
1081}
1082
1083/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001084 * xmlSchemaPMissingAttrErr:
1085 * @ctxt: the schema validation context
1086 * @ownerDes: the designation of the owner
1087 * @ownerName: the name of the owner
1088 * @ownerItem: the owner as a schema object
1089 * @ownerElem: the owner as an element node
1090 * @node: the parent element node of the missing attribute node
1091 * @type: the corresponding type of the attribute node
1092 *
1093 * Reports an illegal attribute.
1094 */
1095static void
1096xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1097 xmlParserErrors error,
1098 xmlChar **ownerDes,
1099 xmlSchemaTypePtr ownerItem,
1100 xmlNodePtr ownerElem,
1101 const char *name,
1102 const char *message)
1103{
1104 xmlChar *des = NULL;
1105
1106 if (ownerDes == NULL)
1107 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1108 else if (*ownerDes == NULL) {
1109 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1110 des = *ownerDes;
1111 } else
1112 des = *ownerDes;
1113 if (message != NULL)
1114 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1115 else
1116 xmlSchemaPErr(ctxt, ownerElem, error,
1117 "%s: The attribute '%s' is required but missing.\n",
1118 BAD_CAST des, BAD_CAST name);
1119 if (ownerDes == NULL)
1120 FREE_AND_NULL(des);
1121}
1122
William M. Brack2f2a6632004-08-20 23:09:47 +00001123/**
1124 * xmlSchemaCompTypeToString:
1125 * @type: the type of the schema item
1126 *
1127 * Returns the component name of a schema item.
1128 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001129static const char *
1130xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1131{
1132 switch (type) {
1133 case XML_SCHEMA_TYPE_SIMPLE:
1134 return("simple type definition");
1135 case XML_SCHEMA_TYPE_COMPLEX:
1136 return("complex type definition");
1137 case XML_SCHEMA_TYPE_ELEMENT:
1138 return("element declaration");
1139 case XML_SCHEMA_TYPE_ATTRIBUTE:
1140 return("attribute declaration");
1141 case XML_SCHEMA_TYPE_GROUP:
1142 return("model group definition");
1143 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1144 return("attribute group definition");
1145 case XML_SCHEMA_TYPE_NOTATION:
1146 return("notation declaration");
1147 default:
1148 return("Not a schema component");
1149 }
1150}
1151/**
1152 * xmlSchemaPResCompAttrErr:
1153 * @ctxt: the schema validation context
1154 * @error: the error code
1155 * @ownerDes: the designation of the owner
1156 * @ownerItem: the owner as a schema object
1157 * @ownerElem: the owner as an element node
1158 * @name: the name of the attribute holding the QName
1159 * @refName: the referenced local name
1160 * @refURI: the referenced namespace URI
1161 * @message: optional message
1162 *
1163 * Used to report QName attribute values that failed to resolve
1164 * to schema components.
1165 */
1166static void
1167xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1168 xmlParserErrors error,
1169 xmlChar **ownerDes,
1170 xmlSchemaTypePtr ownerItem,
1171 xmlNodePtr ownerElem,
1172 const char *name,
1173 const xmlChar *refName,
1174 const xmlChar *refURI,
1175 xmlSchemaTypeType refType,
1176 const char *refTypeStr)
1177{
1178 xmlChar *des = NULL, *strA = NULL;
1179
1180 if (ownerDes == NULL)
1181 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1182 else if (*ownerDes == NULL) {
1183 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1184 des = *ownerDes;
1185 } else
1186 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001187 if (refTypeStr == NULL)
1188 refTypeStr = xmlSchemaCompTypeToString(refType);
1189 xmlSchemaPErrExt(ctxt, ownerElem, error,
1190 NULL, NULL, NULL,
1191 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1192 "%s.\n", BAD_CAST des, BAD_CAST name,
1193 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1194 BAD_CAST refTypeStr, NULL);
1195 if (ownerDes == NULL)
1196 FREE_AND_NULL(des)
1197 FREE_AND_NULL(strA)
1198}
1199
William M. Brack2f2a6632004-08-20 23:09:47 +00001200/**
1201 * xmlSchemaPCustomAttrErr:
1202 * @ctxt: the schema parser context
1203 * @error: the error code
1204 * @ownerDes: the designation of the owner
1205 * @ownerItem: the owner as a schema object
1206 * @attr: the illegal attribute node
1207 *
1208 * Reports an illegal attribute during the parse.
1209 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001210static void
1211xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001212 xmlParserErrors error,
1213 xmlChar **ownerDes,
1214 xmlSchemaTypePtr ownerItem,
1215 xmlAttrPtr attr,
1216 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001217{
1218 xmlChar *des = NULL;
1219
1220 if (ownerDes == NULL)
1221 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1222 else if (*ownerDes == NULL) {
1223 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1224 des = *ownerDes;
1225 } else
1226 des = *ownerDes;
1227 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1228 "%s, attribute '%s': %s.\n",
1229 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1230 if (ownerDes == NULL)
1231 FREE_AND_NULL(des);
1232}
1233
1234/**
1235 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001236 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001237 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001238 * @ownerDes: the designation of the attribute's owner
1239 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001240 * @attr: the illegal attribute node
1241 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001242 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001243 */
1244static void
1245xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1246 xmlParserErrors error,
1247 xmlChar **ownerDes,
1248 xmlSchemaTypePtr ownerItem,
1249 xmlAttrPtr attr)
1250{
1251 xmlChar *des = NULL, *strA = NULL;
1252
1253 if (ownerDes == NULL)
1254 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1255 else if (*ownerDes == NULL) {
1256 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1257 des = *ownerDes;
1258 } else
1259 des = *ownerDes;
1260 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1261 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1262 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1263 if (ownerDes == NULL)
1264 FREE_AND_NULL(des);
1265 FREE_AND_NULL(strA);
1266}
1267
William M. Brack2f2a6632004-08-20 23:09:47 +00001268/**
1269 * xmlSchemaPAquireDes:
1270 * @des: the first designation
1271 * @itemDes: the second designation
1272 * @item: the schema item
1273 * @itemElem: the node of the schema item
1274 *
1275 * Creates a designation for an item.
1276 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001277static void
1278xmlSchemaPAquireDes(xmlChar **des,
1279 xmlChar **itemDes,
1280 xmlSchemaTypePtr item,
1281 xmlNodePtr itemElem)
1282{
1283 if (itemDes == NULL)
1284 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1285 else if (*itemDes == NULL) {
1286 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1287 *des = *itemDes;
1288 } else
1289 *des = *itemDes;
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: an optional param for the error message
1301 * @str2: an optional param for the error message
1302 * @str3: an optional param for the error message
1303 *
1304 * Reports an error during parsing.
1305 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001306static void
1307xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1308 xmlParserErrors error,
1309 xmlChar **itemDes,
1310 xmlSchemaTypePtr item,
1311 xmlNodePtr itemElem,
1312 const char *message,
1313 const xmlChar *str1,
1314 const xmlChar *str2,
1315 const xmlChar *str3)
1316{
1317 xmlChar *des = NULL, *msg = NULL;
1318
1319 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1320 msg = xmlStrdup(BAD_CAST "%s: ");
1321 msg = xmlStrcat(msg, (const xmlChar *) message);
1322 msg = xmlStrcat(msg, BAD_CAST ".\n");
1323 if ((itemElem == NULL) && (item != NULL))
1324 itemElem = item->node;
1325 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1326 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1327 if (itemDes == NULL)
1328 FREE_AND_NULL(des);
1329 FREE_AND_NULL(msg);
1330}
1331
William M. Brack2f2a6632004-08-20 23:09:47 +00001332/**
1333 * xmlSchemaPCustomErr:
1334 * @ctxt: the schema parser context
1335 * @error: the error code
1336 * @itemDes: the designation of the schema item
1337 * @item: the schema item
1338 * @itemElem: the node of the schema item
1339 * @message: the error message
1340 * @str1: the optional param for the error message
1341 *
1342 * Reports an error during parsing.
1343 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001344static void
1345xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1346 xmlParserErrors error,
1347 xmlChar **itemDes,
1348 xmlSchemaTypePtr item,
1349 xmlNodePtr itemElem,
1350 const char *message,
1351 const xmlChar *str1)
1352{
1353 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1354 str1, NULL, NULL);
1355}
1356
William M. Brack2f2a6632004-08-20 23:09:47 +00001357/**
1358 * xmlSchemaPAttrUseErr:
1359 * @ctxt: the schema parser context
1360 * @error: the error code
1361 * @itemDes: the designation of the schema type
1362 * @item: the schema type
1363 * @itemElem: the node of the schema type
1364 * @attr: the invalid schema attribute
1365 * @message: the error message
1366 * @str1: the optional param for the error message
1367 *
1368 * Reports an attribute use error during parsing.
1369 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001370static void
1371xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1372 xmlParserErrors error,
1373 xmlChar **itemDes,
1374 xmlSchemaTypePtr item,
1375 xmlNodePtr itemElem,
1376 const xmlSchemaAttributePtr attr,
1377 const char *message,
1378 const xmlChar *str1)
1379{
1380 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1381
1382 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1383 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1384 xmlSchemaGetAttrName(attr));
1385 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1386 msg = xmlStrcat(msg, (const xmlChar *) message);
1387 msg = xmlStrcat(msg, BAD_CAST ".\n");
1388 if ((itemElem == NULL) && (item != NULL))
1389 itemElem = item->node;
1390 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1391 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1392 if (itemDes == NULL)
1393 FREE_AND_NULL(des);
1394 FREE_AND_NULL(strA);
1395 xmlFree(msg);
1396}
1397
William M. Brack2f2a6632004-08-20 23:09:47 +00001398/**
1399 * xmlSchemaPIllegalFacetAtomicErr:
1400 * @ctxt: the schema parser context
1401 * @error: the error code
1402 * @itemDes: the designation of the type
1403 * @item: the schema type
1404 * @baseItem: the base type of type
1405 * @facet: the illegal facet
1406 *
1407 * Reports an illegal facet for atomic simple types.
1408 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001409static void
1410xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1411 xmlParserErrors error,
1412 xmlChar **itemDes,
1413 xmlSchemaTypePtr item,
1414 xmlSchemaTypePtr baseItem,
1415 xmlSchemaFacetPtr facet)
1416{
1417 xmlChar *des = NULL, *strT = NULL;
1418
1419 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1420 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1421 "%s: The facet '%s' is not allowed on types derived from the "
1422 "type %s.\n",
1423 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1424 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1425 NULL, NULL);
1426 if (itemDes == NULL)
1427 FREE_AND_NULL(des);
1428 FREE_AND_NULL(strT);
1429}
1430
William M. Brack2f2a6632004-08-20 23:09:47 +00001431/**
1432 * xmlSchemaPIllegalFacetListUnionErr:
1433 * @ctxt: the schema parser context
1434 * @error: the error code
1435 * @itemDes: the designation of the schema item involved
1436 * @item: the schema item involved
1437 * @facet: the illegal facet
1438 *
1439 * Reports an illegal facet for <list> and <union>.
1440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001441static void
1442xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1443 xmlParserErrors error,
1444 xmlChar **itemDes,
1445 xmlSchemaTypePtr item,
1446 xmlSchemaFacetPtr facet)
1447{
1448 xmlChar *des = NULL, *strT = NULL;
1449
1450 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1451 xmlSchemaPErr(ctxt, item->node, error,
1452 "%s: The facet '%s' is not allowed.\n",
1453 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1454 if (itemDes == NULL)
1455 FREE_AND_NULL(des);
1456 FREE_AND_NULL(strT);
1457}
1458
1459/**
1460 * xmlSchemaPMutualExclAttrErr:
1461 * @ctxt: the schema validation context
1462 * @error: the error code
1463 * @elemDes: the designation of the parent element node
1464 * @attr: the bad attribute node
1465 * @type: the corresponding type of the attribute node
1466 *
1467 * Reports an illegal attribute.
1468 */
1469static void
1470xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1471 xmlParserErrors error,
1472 xmlChar **ownerDes,
1473 xmlSchemaTypePtr ownerItem,
1474 xmlAttrPtr attr,
1475 const char *name1,
1476 const char *name2)
1477{
1478 xmlChar *des = NULL;
1479
1480 if (ownerDes == NULL)
1481 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1482 else if (*ownerDes == NULL) {
1483 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1484 des = *ownerDes;
1485 } else
1486 des = *ownerDes;
1487 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1488 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1489 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1490 if (ownerDes == NULL)
1491 FREE_AND_NULL(des)
1492}
1493
1494/**
1495 * xmlSchemaPSimpleTypeErr:
1496 * @ctxt: the schema validation context
1497 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001498 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001499 * @ownerDes: the designation of the owner
1500 * @ownerItem: the schema object if existent
1501 * @node: the validated node
1502 * @value: the validated value
1503 *
1504 * Reports a simple type validation error.
1505 * TODO: Should this report the value of an element as well?
1506 */
1507static void
1508xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1509 xmlParserErrors error,
1510 xmlChar **ownerDes,
1511 xmlSchemaTypePtr ownerItem,
1512 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001513 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001514 const char *typeDes,
1515 const xmlChar *value,
1516 const char *message,
1517 const xmlChar *str1,
1518 const xmlChar *str2)
1519{
William M. Brack2f2a6632004-08-20 23:09:47 +00001520 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001521
1522 if (ownerDes == NULL)
1523 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1524 else if (*ownerDes == NULL) {
1525 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1526 des = *ownerDes;
1527 } else
1528 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001529 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001530 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001531 if (message == NULL) {
1532 /*
1533 * Use default messages.
1534 */
1535 if (node->type == XML_ATTRIBUTE_NODE) {
1536 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1537 "%s, attribute '%s' [%s]: The value '%s' is not "
1538 "valid.\n",
1539 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1540 node->name), BAD_CAST typeDes, value, NULL);
1541 } else {
1542 xmlSchemaPErr(ctxt, node, error,
1543 "%s [%s]: The character content is not valid.\n",
1544 BAD_CAST des, BAD_CAST typeDes);
1545 }
1546 } else {
1547 xmlChar *msg;
1548
1549 msg = xmlStrdup(BAD_CAST "%s");
1550 if (node->type == XML_ATTRIBUTE_NODE)
1551 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1552 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1553 msg = xmlStrcat(msg, (const xmlChar *) message);
1554 msg = xmlStrcat(msg, BAD_CAST ".\n");
1555 if (node->type == XML_ATTRIBUTE_NODE) {
1556 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1557 (const char *) msg,
1558 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1559 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1560 } else {
1561 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1562 (const char *) msg,
1563 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1564 }
1565 xmlFree(msg);
1566 }
1567 /* Cleanup. */
1568 FREE_AND_NULL(strA)
1569 FREE_AND_NULL(strT)
1570 if (ownerDes == NULL)
1571 FREE_AND_NULL(des)
1572}
1573
William M. Brack2f2a6632004-08-20 23:09:47 +00001574/**
1575 * xmlSchemaPContentErr:
1576 * @ctxt: the schema parser context
1577 * @error: the error code
1578 * @onwerDes: the designation of the holder of the content
1579 * @ownerItem: the owner item of the holder of the content
1580 * @ownerElem: the node of the holder of the content
1581 * @child: the invalid child node
1582 * @message: the optional error message
1583 * @content: the optional string describing the correct content
1584 *
1585 * Reports an error concerning the content of a schema element.
1586 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001587static void
1588xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1589 xmlParserErrors error,
1590 xmlChar **ownerDes,
1591 xmlSchemaTypePtr ownerItem,
1592 xmlNodePtr ownerElem,
1593 xmlNodePtr child,
1594 const char *message,
1595 const char *content)
1596{
1597 xmlChar *des = NULL;
1598
1599 if (ownerDes == NULL)
1600 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1601 else if (*ownerDes == NULL) {
1602 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1603 des = *ownerDes;
1604 } else
1605 des = *ownerDes;
1606 if (message != NULL)
1607 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1608 "%s: %s.\n",
1609 BAD_CAST des, BAD_CAST message);
1610 else {
1611 if (content != NULL) {
1612 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1613 "%s: The content is not valid. Expected is %s.\n",
1614 BAD_CAST des, BAD_CAST content);
1615 } else {
1616 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1617 "%s: The content is not valid.\n",
1618 BAD_CAST des, NULL);
1619 }
1620 }
1621 if (ownerDes == NULL)
1622 FREE_AND_NULL(des)
1623}
1624
1625/**
1626 * xmlSchemaVIllegalAttrErr:
1627 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001628 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001629 * @attr: the illegal attribute node
1630 *
1631 * Reports an illegal attribute.
1632 */
1633static void
1634xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001635 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001636 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001637{
1638 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001639
1640 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1641 error,
1642 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001643 "%s: The attribute '%s' is not allowed.\n",
1644 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1645 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1646 FREE_AND_NULL(strE)
1647 FREE_AND_NULL(strA)
1648}
1649
William M. Brack2f2a6632004-08-20 23:09:47 +00001650/**
1651 * xmlSchemaVCustomErr:
1652 * @ctxt: the schema validation context
1653 * @error: the error code
1654 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001655 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001656 * @message: the error message
1657 * @str1: the optional param for the message
1658 *
1659 * Reports a validation error.
1660 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001661static void
1662xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1663 xmlParserErrors error,
1664 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001665 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001666 const char *message,
1667 const xmlChar *str1)
1668{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001669 xmlChar *msg = NULL, *str = NULL;
1670
1671 if (node == NULL) {
1672 xmlSchemaVErr(ctxt, NULL,
1673 XML_SCHEMAV_INTERNAL,
1674 "Internal error: xmlSchemaVCustomErr, no node "
1675 "given.\n", NULL, NULL);
1676 return;
1677 }
1678 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1679 if (node->type != XML_DOCUMENT_NODE) {
1680 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1681 if (type != NULL) {
1682 msg = xmlStrcat(msg, BAD_CAST " [");
1683 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1684 msg = xmlStrcat(msg, BAD_CAST "]");
1685 }
1686 msg = xmlStrcat(msg, BAD_CAST ": ");
1687 } else
1688 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001689 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001690 msg = xmlStrcat(msg, BAD_CAST ".\n");
1691 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1692 FREE_AND_NULL(msg)
1693 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694}
1695
William M. Brack2f2a6632004-08-20 23:09:47 +00001696/**
1697 * xmlSchemaWildcardPCToString:
1698 * @pc: the type of processContents
1699 *
1700 * Returns a string representation of the type of
1701 * processContents.
1702 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001703static const char *
1704xmlSchemaWildcardPCToString(int pc)
1705{
1706 switch (pc) {
1707 case XML_SCHEMAS_ANY_SKIP:
1708 return ("skip");
1709 case XML_SCHEMAS_ANY_LAX:
1710 return ("lax");
1711 case XML_SCHEMAS_ANY_STRICT:
1712 return ("strict");
1713 default:
1714 return ("invalid process contents");
1715 }
1716}
1717
William M. Brack2f2a6632004-08-20 23:09:47 +00001718/**
1719 * xmlSchemaVWildcardErr:
1720 * @ctxt: the schema validation context
1721 * @error: the error code
1722 * @node: the validated node
1723 * @wild: the wildcard used
1724 * @message: the error message
1725 *
1726 * Reports an validation-by-wildcard error.
1727 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001728static void
1729xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1730 xmlParserErrors error,
1731 xmlNodePtr node,
1732 xmlSchemaWildcardPtr wild,
1733 const char *message)
1734{
1735 xmlChar *des = NULL, *msg = NULL;
1736
1737 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1738 msg = xmlStrdup(BAD_CAST "%s, [");
1739 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
1740 msg = xmlStrcat(msg, BAD_CAST " WC]: ");
1741 msg = xmlStrcat(msg, (const xmlChar *) message);
1742 msg = xmlStrcat(msg, BAD_CAST ".\n");
1743 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1744 FREE_AND_NULL(des);
1745 FREE_AND_NULL(msg);
1746}
1747
1748/**
1749 * xmlSchemaVMissingAttrErr:
1750 * @ctxt: the schema validation context
1751 * @node: the parent element node of the missing attribute node
1752 * @type: the corresponding type of the attribute node
1753 *
1754 * Reports an illegal attribute.
1755 */
1756static void
1757xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1758 xmlNodePtr elem,
1759 xmlSchemaAttributePtr type)
1760{
1761 const xmlChar *name, *uri;
1762 xmlChar *strE = NULL, *strA = NULL;
1763
1764 if (type->ref != NULL) {
1765 name = type->ref;
1766 uri = type->refNs;
1767 } else {
1768 name = type->name;
1769 uri = type->targetNamespace;
1770 }
1771 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001772 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1773 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001774 "%s: The attribute %s is required but missing.\n",
1775 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1776 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1777 FREE_AND_NULL(strE)
1778 FREE_AND_NULL(strA)
1779}
1780
Daniel Veillard4255d502002-04-16 15:50:10 +00001781/************************************************************************
1782 * *
1783 * Allocation functions *
1784 * *
1785 ************************************************************************/
1786
1787/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001788 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001789 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001790 *
1791 * Allocate a new Schema structure.
1792 *
1793 * Returns the newly allocated structure or NULL in case or error
1794 */
1795static xmlSchemaPtr
1796xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1797{
1798 xmlSchemaPtr ret;
1799
1800 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1801 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001802 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001803 return (NULL);
1804 }
1805 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001806 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001807 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001808
1809 return (ret);
1810}
1811
1812/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001813 * xmlSchemaNewSchema:
1814 * @ctxt: a schema validation context
1815 *
1816 * Allocate a new Schema structure.
1817 *
1818 * Returns the newly allocated structure or NULL in case or error
1819 */
1820static xmlSchemaAssemblePtr
1821xmlSchemaNewAssemble(void)
1822{
1823 xmlSchemaAssemblePtr ret;
1824
1825 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1826 if (ret == NULL) {
1827 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1828 return (NULL);
1829 }
1830 memset(ret, 0, sizeof(xmlSchemaAssemble));
1831 ret->items = NULL;
1832 return (ret);
1833}
1834
1835/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001836 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001837 *
1838 * Allocate a new Facet structure.
1839 *
1840 * Returns the newly allocated structure or NULL in case or error
1841 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001842xmlSchemaFacetPtr
1843xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001844{
1845 xmlSchemaFacetPtr ret;
1846
1847 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1848 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001849 return (NULL);
1850 }
1851 memset(ret, 0, sizeof(xmlSchemaFacet));
1852
1853 return (ret);
1854}
1855
1856/**
1857 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001858 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001859 * @node: a node
1860 *
1861 * Allocate a new annotation structure.
1862 *
1863 * Returns the newly allocated structure or NULL in case or error
1864 */
1865static xmlSchemaAnnotPtr
1866xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1867{
1868 xmlSchemaAnnotPtr ret;
1869
1870 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1871 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001872 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001873 return (NULL);
1874 }
1875 memset(ret, 0, sizeof(xmlSchemaAnnot));
1876 ret->content = node;
1877 return (ret);
1878}
1879
1880/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001881 * xmlSchemaFreeAnnot:
1882 * @annot: a schema type structure
1883 *
1884 * Deallocate a annotation structure
1885 */
1886static void
1887xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1888{
1889 if (annot == NULL)
1890 return;
1891 xmlFree(annot);
1892}
1893
1894/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001895 * xmlSchemaFreeImport:
1896 * @import: a schema import structure
1897 *
1898 * Deallocate an import structure
1899 */
1900static void
1901xmlSchemaFreeImport(xmlSchemaImportPtr import)
1902{
1903 if (import == NULL)
1904 return;
1905
1906 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001907 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001908 xmlFree(import);
1909}
1910
1911/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001912 * xmlSchemaFreeInclude:
1913 * @include: a schema include structure
1914 *
1915 * Deallocate an include structure
1916 */
1917static void
1918xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1919{
1920 if (include == NULL)
1921 return;
1922
1923 xmlFreeDoc(include->doc);
1924 xmlFree(include);
1925}
1926
1927/**
1928 * xmlSchemaFreeIncludeList:
1929 * @includes: a schema include list
1930 *
1931 * Deallocate an include structure
1932 */
1933static void
1934xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1935{
1936 xmlSchemaIncludePtr next;
1937
1938 while (includes != NULL) {
1939 next = includes->next;
1940 xmlSchemaFreeInclude(includes);
1941 includes = next;
1942 }
1943}
1944
1945/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001946 * xmlSchemaFreeNotation:
1947 * @schema: a schema notation structure
1948 *
1949 * Deallocate a Schema Notation structure.
1950 */
1951static void
1952xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1953{
1954 if (nota == NULL)
1955 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001956 xmlFree(nota);
1957}
1958
1959/**
1960 * xmlSchemaFreeAttribute:
1961 * @schema: a schema attribute structure
1962 *
1963 * Deallocate a Schema Attribute structure.
1964 */
1965static void
1966xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
1967{
1968 if (attr == NULL)
1969 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001970 if (attr->annot != NULL)
1971 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001972 if (attr->defVal != NULL)
1973 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00001974 xmlFree(attr);
1975}
1976
1977/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001978 * xmlSchemaFreeWildcardNsSet:
1979 * set: a schema wildcard namespace
1980 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001981 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00001982 */
1983static void
1984xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
1985{
1986 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001987
Daniel Veillard3646d642004-06-02 19:19:14 +00001988 while (set != NULL) {
1989 next = set->next;
1990 xmlFree(set);
1991 set = next;
1992 }
1993}
1994
1995/**
1996 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00001997 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00001998 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00001999 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002000 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002001void
Daniel Veillard3646d642004-06-02 19:19:14 +00002002xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2003{
2004 if (wildcard == NULL)
2005 return;
2006 if (wildcard->annot != NULL)
2007 xmlSchemaFreeAnnot(wildcard->annot);
2008 if (wildcard->nsSet != NULL)
2009 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2010 if (wildcard->negNsSet != NULL)
2011 xmlFree(wildcard->negNsSet);
2012 xmlFree(wildcard);
2013}
2014
2015/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002016 * xmlSchemaFreeAttributeGroup:
2017 * @schema: a schema attribute group structure
2018 *
2019 * Deallocate a Schema Attribute Group structure.
2020 */
2021static void
2022xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2023{
2024 if (attr == NULL)
2025 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002026 if (attr->annot != NULL)
2027 xmlSchemaFreeAnnot(attr->annot);
2028 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2029 (attr->attributeWildcard != NULL))
2030 xmlSchemaFreeWildcard(attr->attributeWildcard);
2031
Daniel Veillard4255d502002-04-16 15:50:10 +00002032 xmlFree(attr);
2033}
2034
2035/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002036 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002037 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002038 *
2039 * Deallocate a list of schema attribute uses.
2040 */
2041static void
2042xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2043{
2044 xmlSchemaAttributeLinkPtr next;
2045
2046 while (attrUse != NULL) {
2047 next = attrUse->next;
2048 xmlFree(attrUse);
2049 attrUse = next;
2050 }
2051}
2052
2053/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002054 * xmlSchemaFreeTypeLinkList:
2055 * @alink: a type link
2056 *
2057 * Deallocate a list of types.
2058 */
2059static void
2060xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2061{
2062 xmlSchemaTypeLinkPtr next;
2063
2064 while (link != NULL) {
2065 next = link->next;
2066 xmlFree(link);
2067 link = next;
2068 }
2069}
2070
2071/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002072 * xmlSchemaFreeElement:
2073 * @schema: a schema element structure
2074 *
2075 * Deallocate a Schema Element structure.
2076 */
2077static void
2078xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2079{
2080 if (elem == NULL)
2081 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002082 if (elem->annot != NULL)
2083 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002084 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002085 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002086 if (elem->defVal != NULL)
2087 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002088 xmlFree(elem);
2089}
2090
2091/**
2092 * xmlSchemaFreeFacet:
2093 * @facet: a schema facet structure
2094 *
2095 * Deallocate a Schema Facet structure.
2096 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002097void
Daniel Veillard4255d502002-04-16 15:50:10 +00002098xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2099{
2100 if (facet == NULL)
2101 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002102 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002103 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002104 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002105 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002106 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002107 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002108 xmlFree(facet);
2109}
2110
2111/**
2112 * xmlSchemaFreeType:
2113 * @type: a schema type structure
2114 *
2115 * Deallocate a Schema Type structure.
2116 */
2117void
2118xmlSchemaFreeType(xmlSchemaTypePtr type)
2119{
2120 if (type == NULL)
2121 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002122 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002123 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002124 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002125 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002126
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002127 facet = type->facets;
2128 while (facet != NULL) {
2129 next = facet->next;
2130 xmlSchemaFreeFacet(facet);
2131 facet = next;
2132 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002133 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002134 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2135 if (type->attributeUses != NULL)
2136 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002137 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002138 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002139 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2140 /*
2141 * NOTE: The only case where an attribute wildcard
2142 * is not owned, is if a complex type inherits it
2143 * from a base type.
2144 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002145 xmlSchemaFreeWildcard(type->attributeWildcard);
2146 }
2147 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002148 if (type->memberTypes != NULL)
2149 xmlSchemaFreeTypeLinkList(type->memberTypes);
2150 if (type->facetSet != NULL) {
2151 xmlSchemaFacetLinkPtr next, link;
2152
2153 link = type->facetSet;
2154 do {
2155 next = link->next;
2156 xmlFree(link);
2157 link = next;
2158 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002159 }
2160 if (type->contModel != NULL)
2161 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002162 xmlFree(type);
2163}
2164
2165/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002166 * xmlSchemaFreeTypeList:
2167 * @type: a schema type structure
2168 *
2169 * Deallocate a Schema Type structure.
2170 */
2171static void
2172xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2173{
2174 xmlSchemaTypePtr next;
2175
2176 while (type != NULL) {
2177 next = type->redef;
2178 xmlSchemaFreeType(type);
2179 type = next;
2180 }
2181}
2182
2183/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002184 * xmlSchemaFree:
2185 * @schema: a schema structure
2186 *
2187 * Deallocate a Schema structure.
2188 */
2189void
2190xmlSchemaFree(xmlSchemaPtr schema)
2191{
2192 if (schema == NULL)
2193 return;
2194
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 if (schema->notaDecl != NULL)
2196 xmlHashFree(schema->notaDecl,
2197 (xmlHashDeallocator) xmlSchemaFreeNotation);
2198 if (schema->attrDecl != NULL)
2199 xmlHashFree(schema->attrDecl,
2200 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2201 if (schema->attrgrpDecl != NULL)
2202 xmlHashFree(schema->attrgrpDecl,
2203 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2204 if (schema->elemDecl != NULL)
2205 xmlHashFree(schema->elemDecl,
2206 (xmlHashDeallocator) xmlSchemaFreeElement);
2207 if (schema->typeDecl != NULL)
2208 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002209 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002210 if (schema->groupDecl != NULL)
2211 xmlHashFree(schema->groupDecl,
2212 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002213 if (schema->schemasImports != NULL)
2214 xmlHashFree(schema->schemasImports,
2215 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002216 if (schema->includes != NULL) {
2217 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002220 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002221 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002222 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002223 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002224 xmlFree(schema);
2225}
2226
2227/************************************************************************
2228 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002229 * Debug functions *
2230 * *
2231 ************************************************************************/
2232
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002233#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002234
Daniel Veillard4255d502002-04-16 15:50:10 +00002235/**
2236 * xmlSchemaElementDump:
2237 * @elem: an element
2238 * @output: the file output
2239 *
2240 * Dump the element
2241 */
2242static void
2243xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002244 const xmlChar * name ATTRIBUTE_UNUSED,
2245 const xmlChar * context ATTRIBUTE_UNUSED,
2246 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002247{
2248 if (elem == NULL)
2249 return;
2250
2251 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002252 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2253 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002254 fprintf(output, ": %s ", elem->name);
2255 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002256 fprintf(output, "namespace '%s' ", namespace);
2257
Daniel Veillard4255d502002-04-16 15:50:10 +00002258 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002259 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002260 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002261 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002262 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002263 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002264 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002265 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002266 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002267 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002268 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002269 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 fprintf(output, "\n");
2271 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002272 fprintf(output, " ");
2273 if (elem->minOccurs != 1)
2274 fprintf(output, "min: %d ", elem->minOccurs);
2275 if (elem->maxOccurs >= UNBOUNDED)
2276 fprintf(output, "max: unbounded\n");
2277 else if (elem->maxOccurs != 1)
2278 fprintf(output, "max: %d\n", elem->maxOccurs);
2279 else
2280 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 }
2282 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002283 fprintf(output, " type: %s", elem->namedType);
2284 if (elem->namedTypeNs != NULL)
2285 fprintf(output, " ns %s\n", elem->namedTypeNs);
2286 else
2287 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 }
2289 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002290 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2291 if (elem->substGroupNs != NULL)
2292 fprintf(output, " ns %s\n", elem->substGroupNs);
2293 else
2294 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002295 }
2296 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002297 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002298}
2299
2300/**
2301 * xmlSchemaAnnotDump:
2302 * @output: the file output
2303 * @annot: a annotation
2304 *
2305 * Dump the annotation
2306 */
2307static void
2308xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2309{
2310 xmlChar *content;
2311
2312 if (annot == NULL)
2313 return;
2314
2315 content = xmlNodeGetContent(annot->content);
2316 if (content != NULL) {
2317 fprintf(output, " Annot: %s\n", content);
2318 xmlFree(content);
2319 } else
2320 fprintf(output, " Annot: empty\n");
2321}
2322
2323/**
2324 * xmlSchemaTypeDump:
2325 * @output: the file output
2326 * @type: a type structure
2327 *
2328 * Dump a SchemaType structure
2329 */
2330static void
2331xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2332{
2333 if (type == NULL) {
2334 fprintf(output, "Type: NULL\n");
2335 return;
2336 }
2337 fprintf(output, "Type: ");
2338 if (type->name != NULL)
2339 fprintf(output, "%s, ", type->name);
2340 else
2341 fprintf(output, "no name");
2342 switch (type->type) {
2343 case XML_SCHEMA_TYPE_BASIC:
2344 fprintf(output, "basic ");
2345 break;
2346 case XML_SCHEMA_TYPE_SIMPLE:
2347 fprintf(output, "simple ");
2348 break;
2349 case XML_SCHEMA_TYPE_COMPLEX:
2350 fprintf(output, "complex ");
2351 break;
2352 case XML_SCHEMA_TYPE_SEQUENCE:
2353 fprintf(output, "sequence ");
2354 break;
2355 case XML_SCHEMA_TYPE_CHOICE:
2356 fprintf(output, "choice ");
2357 break;
2358 case XML_SCHEMA_TYPE_ALL:
2359 fprintf(output, "all ");
2360 break;
2361 case XML_SCHEMA_TYPE_UR:
2362 fprintf(output, "ur ");
2363 break;
2364 case XML_SCHEMA_TYPE_RESTRICTION:
2365 fprintf(output, "restriction ");
2366 break;
2367 case XML_SCHEMA_TYPE_EXTENSION:
2368 fprintf(output, "extension ");
2369 break;
2370 default:
2371 fprintf(output, "unknowntype%d ", type->type);
2372 break;
2373 }
2374 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002375 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002376 }
2377 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002378 case XML_SCHEMA_CONTENT_UNKNOWN:
2379 fprintf(output, "unknown ");
2380 break;
2381 case XML_SCHEMA_CONTENT_EMPTY:
2382 fprintf(output, "empty ");
2383 break;
2384 case XML_SCHEMA_CONTENT_ELEMENTS:
2385 fprintf(output, "element ");
2386 break;
2387 case XML_SCHEMA_CONTENT_MIXED:
2388 fprintf(output, "mixed ");
2389 break;
2390 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002391 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002392 break;
2393 case XML_SCHEMA_CONTENT_BASIC:
2394 fprintf(output, "basic ");
2395 break;
2396 case XML_SCHEMA_CONTENT_SIMPLE:
2397 fprintf(output, "simple ");
2398 break;
2399 case XML_SCHEMA_CONTENT_ANY:
2400 fprintf(output, "any ");
2401 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002402 }
2403 fprintf(output, "\n");
2404 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002405 fprintf(output, " ");
2406 if (type->minOccurs != 1)
2407 fprintf(output, "min: %d ", type->minOccurs);
2408 if (type->maxOccurs >= UNBOUNDED)
2409 fprintf(output, "max: unbounded\n");
2410 else if (type->maxOccurs != 1)
2411 fprintf(output, "max: %d\n", type->maxOccurs);
2412 else
2413 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 }
2415 if (type->annot != NULL)
2416 xmlSchemaAnnotDump(output, type->annot);
2417 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002418 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002419
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002420 fprintf(output, " subtypes: ");
2421 while (sub != NULL) {
2422 fprintf(output, "%s ", sub->name);
2423 sub = sub->next;
2424 }
2425 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002426 }
2427
2428}
2429
2430/**
2431 * xmlSchemaDump:
2432 * @output: the file output
2433 * @schema: a schema structure
2434 *
2435 * Dump a Schema structure.
2436 */
2437void
2438xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2439{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002440 if (output == NULL)
2441 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002442 if (schema == NULL) {
2443 fprintf(output, "Schemas: NULL\n");
2444 return;
2445 }
2446 fprintf(output, "Schemas: ");
2447 if (schema->name != NULL)
2448 fprintf(output, "%s, ", schema->name);
2449 else
2450 fprintf(output, "no name, ");
2451 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002452 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002453 else
2454 fprintf(output, "no target namespace");
2455 fprintf(output, "\n");
2456 if (schema->annot != NULL)
2457 xmlSchemaAnnotDump(output, schema->annot);
2458
2459 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2460 output);
2461 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002462 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002463}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002464#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002465
2466/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002467 * *
2468 * Utilities *
2469 * *
2470 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002471
Daniel Veillardc0826a72004-08-10 14:17:33 +00002472/**
2473 * xmlSchemaGetPropNode:
2474 * @node: the element node
2475 * @name: the name of the attribute
2476 *
2477 * Seeks an attribute with a name of @name in
2478 * no namespace.
2479 *
2480 * Returns the attribute or NULL if not present.
2481 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002482static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002483xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002484{
2485 xmlAttrPtr prop;
2486
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 if ((node == NULL) || (name == NULL))
2488 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002489 prop = node->properties;
2490 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002491 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2492 return(prop);
2493 prop = prop->next;
2494 }
2495 return (NULL);
2496}
2497
2498/**
2499 * xmlSchemaGetPropNodeNs:
2500 * @node: the element node
2501 * @uri: the uri
2502 * @name: the name of the attribute
2503 *
2504 * Seeks an attribute with a local name of @name and
2505 * a namespace URI of @uri.
2506 *
2507 * Returns the attribute or NULL if not present.
2508 */
2509static xmlAttrPtr
2510xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2511{
2512 xmlAttrPtr prop;
2513
2514 if ((node == NULL) || (name == NULL))
2515 return(NULL);
2516 prop = node->properties;
2517 while (prop != NULL) {
2518 if ((prop->ns != NULL) &&
2519 xmlStrEqual(prop->name, BAD_CAST name) &&
2520 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002521 return(prop);
2522 prop = prop->next;
2523 }
2524 return (NULL);
2525}
2526
2527static const xmlChar *
2528xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2529{
2530 xmlChar *val;
2531 const xmlChar *ret;
2532
2533 val = xmlNodeGetContent(node);
2534 if (val == NULL)
2535 return(NULL);
2536 ret = xmlDictLookup(ctxt->dict, val, -1);
2537 xmlFree(val);
2538 return(ret);
2539}
2540
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002541/**
2542 * xmlSchemaGetProp:
2543 * @ctxt: the parser context
2544 * @node: the node
2545 * @name: the property name
2546 *
2547 * Read a attribute value and internalize the string
2548 *
2549 * Returns the string or NULL if not present.
2550 */
2551static const xmlChar *
2552xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2553 const char *name)
2554{
2555 xmlChar *val;
2556 const xmlChar *ret;
2557
2558 val = xmlGetProp(node, BAD_CAST name);
2559 if (val == NULL)
2560 return(NULL);
2561 ret = xmlDictLookup(ctxt->dict, val, -1);
2562 xmlFree(val);
2563 return(ret);
2564}
2565
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002566/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002567 * *
2568 * Parsing functions *
2569 * *
2570 ************************************************************************/
2571
2572/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002573 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002574 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002575 * @name: the element name
2576 * @ns: the element namespace
2577 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002578 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002579 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002580 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002581 */
2582static xmlSchemaElementPtr
2583xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002584 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002585{
2586 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002587
2588 if ((name == NULL) || (schema == NULL))
2589 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002590
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002591 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002592 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002593 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002594 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002595 } else
2596 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002597 /*
2598 * This one was removed, since top level element declarations have
2599 * the target namespace specified in targetNamespace of the <schema>
2600 * information element, even if elementFormDefault is "unqualified".
2601 */
2602
2603 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002604 if (xmlStrEqual(namespace, schema->targetNamespace))
2605 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2606 else
2607 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002608 if ((ret != NULL) &&
2609 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002610 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002611 }
William M. Bracke7091952004-05-11 15:09:58 +00002612 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002613
William M. Brack2f2a6632004-08-20 23:09:47 +00002614 /*
2615 * Removed since imported components will be hold by the main schema only.
2616 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002617 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002618 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002619 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002621 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002622 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002623 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2624 return (ret);
2625 } else
2626 ret = NULL;
2627 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002628 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002629#ifdef DEBUG
2630 if (ret == NULL) {
2631 if (namespace == NULL)
2632 fprintf(stderr, "Unable to lookup type %s", name);
2633 else
2634 fprintf(stderr, "Unable to lookup type %s:%s", name,
2635 namespace);
2636 }
2637#endif
2638 return (ret);
2639}
2640
2641/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002642 * xmlSchemaGetType:
2643 * @schema: the schemas context
2644 * @name: the type name
2645 * @ns: the type namespace
2646 *
2647 * Lookup a type in the schemas or the predefined types
2648 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002649 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002650 */
2651static xmlSchemaTypePtr
2652xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002653 const xmlChar * namespace)
2654{
Daniel Veillard4255d502002-04-16 15:50:10 +00002655 xmlSchemaTypePtr ret;
2656
2657 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002658 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002660 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002661 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002662 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002663 }
2664 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002665 if (ret != NULL)
2666 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002667 /*
2668 * Removed, since the imported components will be grafted on the
2669 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002670 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002671 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002672 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002673 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002674 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002675 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002676 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2677 return (ret);
2678 } else
2679 ret = NULL;
2680 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002681 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002682#ifdef DEBUG
2683 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002684 if (namespace == NULL)
2685 fprintf(stderr, "Unable to lookup type %s", name);
2686 else
2687 fprintf(stderr, "Unable to lookup type %s:%s", name,
2688 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002689 }
2690#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002692}
2693
Daniel Veillard3646d642004-06-02 19:19:14 +00002694/**
2695 * xmlSchemaGetAttribute:
2696 * @schema: the context of the schema
2697 * @name: the name of the attribute
2698 * @ns: the target namespace of the attribute
2699 *
2700 * Lookup a an attribute in the schema or imported schemas
2701 *
2702 * Returns the attribute declaration or NULL if not found.
2703 */
2704static xmlSchemaAttributePtr
2705xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2706 const xmlChar * namespace)
2707{
2708 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002709
2710 if ((name == NULL) || (schema == NULL))
2711 return (NULL);
2712
2713
2714 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2715 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2716 return (ret);
2717 else
2718 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002719 /*
2720 * Removed, since imported components will be hold by the main schema only.
2721 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002722 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002723 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002724 else
2725 import = xmlHashLookup(schema->schemasImports, namespace);
2726 if (import != NULL) {
2727 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2728 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2729 return (ret);
2730 } else
2731 ret = NULL;
2732 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002733 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002734#ifdef DEBUG
2735 if (ret == NULL) {
2736 if (namespace == NULL)
2737 fprintf(stderr, "Unable to lookup attribute %s", name);
2738 else
2739 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2740 namespace);
2741 }
2742#endif
2743 return (ret);
2744}
2745
2746/**
2747 * xmlSchemaGetAttributeGroup:
2748 * @schema: the context of the schema
2749 * @name: the name of the attribute group
2750 * @ns: the target namespace of the attribute group
2751 *
2752 * Lookup a an attribute group in the schema or imported schemas
2753 *
2754 * Returns the attribute group definition or NULL if not found.
2755 */
2756static xmlSchemaAttributeGroupPtr
2757xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2758 const xmlChar * namespace)
2759{
2760 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002761
2762 if ((name == NULL) || (schema == NULL))
2763 return (NULL);
2764
2765
2766 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2767 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2768 return (ret);
2769 else
2770 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002771 /*
2772 * Removed since imported components will be hold by the main schema only.
2773 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002774 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002775 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002776 else
2777 import = xmlHashLookup(schema->schemasImports, namespace);
2778 if (import != NULL) {
2779 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2780 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2781 return (ret);
2782 else
2783 ret = NULL;
2784 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002785 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002786#ifdef DEBUG
2787 if (ret == NULL) {
2788 if (namespace == NULL)
2789 fprintf(stderr, "Unable to lookup attribute group %s", name);
2790 else
2791 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2792 namespace);
2793 }
2794#endif
2795 return (ret);
2796}
2797
2798/**
2799 * xmlSchemaGetGroup:
2800 * @schema: the context of the schema
2801 * @name: the name of the group
2802 * @ns: the target namespace of the group
2803 *
2804 * Lookup a group in the schema or imported schemas
2805 *
2806 * Returns the group definition or NULL if not found.
2807 */
2808static xmlSchemaTypePtr
2809xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2810 const xmlChar * namespace)
2811{
2812 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002813
2814 if ((name == NULL) || (schema == NULL))
2815 return (NULL);
2816
2817
2818 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2819 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2820 return (ret);
2821 else
2822 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002823 /*
2824 * Removed since imported components will be hold by the main schema only.
2825 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002826 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002827 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002828 else
2829 import = xmlHashLookup(schema->schemasImports, namespace);
2830 if (import != NULL) {
2831 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2832 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2833 return (ret);
2834 else
2835 ret = NULL;
2836 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002837 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002838#ifdef DEBUG
2839 if (ret == NULL) {
2840 if (namespace == NULL)
2841 fprintf(stderr, "Unable to lookup group %s", name);
2842 else
2843 fprintf(stderr, "Unable to lookup group %s:%s", name,
2844 namespace);
2845 }
2846#endif
2847 return (ret);
2848}
2849
Daniel Veillard4255d502002-04-16 15:50:10 +00002850/************************************************************************
2851 * *
2852 * Parsing functions *
2853 * *
2854 ************************************************************************/
2855
2856#define IS_BLANK_NODE(n) \
2857 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2858
2859/**
2860 * xmlSchemaIsBlank:
2861 * @str: a string
2862 *
2863 * Check if a string is ignorable
2864 *
2865 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2866 */
2867static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002868xmlSchemaIsBlank(xmlChar * str)
2869{
Daniel Veillard4255d502002-04-16 15:50:10 +00002870 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002871 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002872 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002873 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002874 return (0);
2875 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002878}
2879
2880/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002881 * xmlSchemaAddAssembledItem:
2882 * @ctxt: a schema parser context
2883 * @schema: the schema being built
2884 * @item: the item
2885 *
2886 * Add a item to the schema's list of current items.
2887 * This is used if the schema was already constructed and
2888 * new schemata need to be added to it.
2889 * *WARNING* this interface is highly subject to change.
2890 *
2891 * Returns 0 if suceeds and -1 if an internal error occurs.
2892 */
2893static int
2894xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2895 xmlSchemaTypePtr item)
2896{
2897 static int growSize = 100;
2898 xmlSchemaAssemblePtr ass;
2899
2900 ass = ctxt->assemble;
2901 if (ass->sizeItems < 0) {
2902 /* If disabled. */
2903 return (0);
2904 }
2905 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002906 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002907 if (ass->items == NULL) {
2908 xmlSchemaPErrMemory(ctxt,
2909 "allocating new item buffer", NULL);
2910 return (-1);
2911 }
2912 ass->sizeItems = growSize;
2913 } else if (ass->sizeItems <= ass->nbItems) {
2914 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002915 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002916 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2917 if (ass->items == NULL) {
2918 xmlSchemaPErrMemory(ctxt,
2919 "growing item buffer", NULL);
2920 ass->sizeItems = 0;
2921 return (-1);
2922 }
2923 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002924 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002925 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2926 return (0);
2927}
2928
2929/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002931 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002932 * @schema: the schema being built
2933 * @name: the item name
2934 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002935 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002936 * *WARNING* this interface is highly subject to change
2937 *
2938 * Returns the new struture or NULL in case of error
2939 */
2940static xmlSchemaNotationPtr
2941xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002942 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002943{
2944 xmlSchemaNotationPtr ret = NULL;
2945 int val;
2946
2947 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2948 return (NULL);
2949
2950 if (schema->notaDecl == NULL)
2951 schema->notaDecl = xmlHashCreate(10);
2952 if (schema->notaDecl == NULL)
2953 return (NULL);
2954
2955 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2956 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002957 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002958 return (NULL);
2959 }
2960 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002961 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002962 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2963 ret);
2964 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002965 /*
2966 * TODO: This should never happen, since a unique name will be computed.
2967 * If it fails, then an other internal error must have occured.
2968 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002969 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
2970 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002971 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002972 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002973 xmlFree(ret);
2974 return (NULL);
2975 }
2976 return (ret);
2977}
2978
2979
2980/**
2981 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002982 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002983 * @schema: the schema being built
2984 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002985 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00002986 *
2987 * Add an XML schema Attrribute declaration
2988 * *WARNING* this interface is highly subject to change
2989 *
2990 * Returns the new struture or NULL in case of error
2991 */
2992static xmlSchemaAttributePtr
2993xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00002994 const xmlChar * name, const xmlChar * namespace,
2995 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00002996{
2997 xmlSchemaAttributePtr ret = NULL;
2998 int val;
2999
3000 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3001 return (NULL);
3002
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003003#ifdef DEBUG
3004 fprintf(stderr, "Adding attribute %s\n", name);
3005 if (namespace != NULL)
3006 fprintf(stderr, " target namespace %s\n", namespace);
3007#endif
3008
Daniel Veillard4255d502002-04-16 15:50:10 +00003009 if (schema->attrDecl == NULL)
3010 schema->attrDecl = xmlHashCreate(10);
3011 if (schema->attrDecl == NULL)
3012 return (NULL);
3013
3014 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3015 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003016 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 return (NULL);
3018 }
3019 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003020 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3021 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003022 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003023 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003024 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003025 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003026 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003027 NULL, NULL, node,
3028 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003029 xmlFree(ret);
3030 return (NULL);
3031 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003032 if (ctxt->assemble != NULL)
3033 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003034 return (ret);
3035}
3036
3037/**
3038 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003039 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 * @schema: the schema being built
3041 * @name: the item name
3042 *
3043 * Add an XML schema Attrribute Group declaration
3044 *
3045 * Returns the new struture or NULL in case of error
3046 */
3047static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003048xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003049 xmlSchemaPtr schema, const xmlChar * name,
3050 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003051{
3052 xmlSchemaAttributeGroupPtr ret = NULL;
3053 int val;
3054
3055 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3056 return (NULL);
3057
3058 if (schema->attrgrpDecl == NULL)
3059 schema->attrgrpDecl = xmlHashCreate(10);
3060 if (schema->attrgrpDecl == NULL)
3061 return (NULL);
3062
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003063 ret =
3064 (xmlSchemaAttributeGroupPtr)
3065 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003066 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003067 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003068 return (NULL);
3069 }
3070 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003071 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003073 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003075 xmlSchemaPCustomErr(ctxt,
3076 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3077 NULL, NULL, node,
3078 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003079 xmlFree(ret);
3080 return (NULL);
3081 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003082 if (ctxt->assemble != NULL)
3083 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003084 return (ret);
3085}
3086
3087/**
3088 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003089 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003090 * @schema: the schema being built
3091 * @name: the type name
3092 * @namespace: the type namespace
3093 *
3094 * Add an XML schema Element declaration
3095 * *WARNING* this interface is highly subject to change
3096 *
3097 * Returns the new struture or NULL in case of error
3098 */
3099static xmlSchemaElementPtr
3100xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003101 const xmlChar * name, const xmlChar * namespace,
3102 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003103{
3104 xmlSchemaElementPtr ret = NULL;
3105 int val;
3106
3107 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3108 return (NULL);
3109
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003110#ifdef DEBUG
3111 fprintf(stderr, "Adding element %s\n", name);
3112 if (namespace != NULL)
3113 fprintf(stderr, " target namespace %s\n", namespace);
3114#endif
3115
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 if (schema->elemDecl == NULL)
3117 schema->elemDecl = xmlHashCreate(10);
3118 if (schema->elemDecl == NULL)
3119 return (NULL);
3120
3121 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3122 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003123 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003124 return (NULL);
3125 }
3126 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003127 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3128 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003129 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003130 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003131 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003132 if (topLevel) {
3133 xmlSchemaPCustomErr(ctxt,
3134 XML_SCHEMAP_REDEFINED_ELEMENT,
3135 NULL, NULL, node,
3136 "A global element declaration with the name '%s' does "
3137 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003138 xmlFree(ret);
3139 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003140 } else {
3141 char buf[30];
3142
3143 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3144 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3145 namespace, ret);
3146 if (val != 0) {
3147 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003148 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003149 NULL, NULL, node,
3150 "Internal error: xmlSchemaAddElement, "
3151 "a dublicate element declaration with the name '%s' "
3152 "could not be added to the hash.", name);
3153 xmlFree(ret);
3154 return (NULL);
3155 }
3156 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003157
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003159 if (ctxt->assemble != NULL)
3160 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003161 return (ret);
3162}
3163
3164/**
3165 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003166 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003167 * @schema: the schema being built
3168 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003169 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003171 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003172 * *WARNING* this interface is highly subject to change
3173 *
3174 * Returns the new struture or NULL in case of error
3175 */
3176static xmlSchemaTypePtr
3177xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003178 const xmlChar * name, const xmlChar * namespace,
3179 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003180{
3181 xmlSchemaTypePtr ret = NULL;
3182 int val;
3183
3184 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3185 return (NULL);
3186
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003187#ifdef DEBUG
3188 fprintf(stderr, "Adding type %s\n", name);
3189 if (namespace != NULL)
3190 fprintf(stderr, " target namespace %s\n", namespace);
3191#endif
3192
Daniel Veillard4255d502002-04-16 15:50:10 +00003193 if (schema->typeDecl == NULL)
3194 schema->typeDecl = xmlHashCreate(10);
3195 if (schema->typeDecl == NULL)
3196 return (NULL);
3197
3198 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3199 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003200 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003201 return (NULL);
3202 }
3203 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003204 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003205 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003206 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003207 if (val != 0) {
3208 if (ctxt->includes == 0) {
3209 xmlSchemaPCustomErr(ctxt,
3210 XML_SCHEMAP_REDEFINED_TYPE,
3211 NULL, NULL, node,
3212 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003213 xmlFree(ret);
3214 return (NULL);
3215 } else {
3216 xmlSchemaTypePtr prev;
3217
3218 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3219 if (prev == NULL) {
3220 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003221 XML_ERR_INTERNAL_ERROR,
3222 "Internal error: xmlSchemaAddType, on type "
3223 "'%s'.\n",
3224 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003225 xmlFree(ret);
3226 return (NULL);
3227 }
3228 ret->redef = prev->redef;
3229 prev->redef = ret;
3230 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003231 }
3232 ret->minOccurs = 1;
3233 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003234 ret->attributeUses = NULL;
3235 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003236 if (ctxt->assemble != NULL)
3237 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003238 return (ret);
3239}
3240
3241/**
3242 * xmlSchemaAddGroup:
3243 * @ctxt: a schema validation context
3244 * @schema: the schema being built
3245 * @name: the group name
3246 *
3247 * Add an XML schema Group definition
3248 *
3249 * Returns the new struture or NULL in case of error
3250 */
3251static xmlSchemaTypePtr
3252xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003253 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003254{
3255 xmlSchemaTypePtr ret = NULL;
3256 int val;
3257
3258 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3259 return (NULL);
3260
3261 if (schema->groupDecl == NULL)
3262 schema->groupDecl = xmlHashCreate(10);
3263 if (schema->groupDecl == NULL)
3264 return (NULL);
3265
3266 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3267 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003268 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003269 return (NULL);
3270 }
3271 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003272 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003273 val =
3274 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3275 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003276 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003277 xmlSchemaPCustomErr(ctxt,
3278 XML_SCHEMAP_REDEFINED_GROUP,
3279 NULL, NULL, node,
3280 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003281 xmlFree(ret);
3282 return (NULL);
3283 }
3284 ret->minOccurs = 1;
3285 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003286 if (ctxt->assemble != NULL)
3287 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003288 return (ret);
3289}
3290
Daniel Veillard3646d642004-06-02 19:19:14 +00003291/**
3292 * xmlSchemaNewWildcardNs:
3293 * @ctxt: a schema validation context
3294 *
3295 * Creates a new wildcard namespace constraint.
3296 *
3297 * Returns the new struture or NULL in case of error
3298 */
3299static xmlSchemaWildcardNsPtr
3300xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3301{
3302 xmlSchemaWildcardNsPtr ret;
3303
3304 ret = (xmlSchemaWildcardNsPtr)
3305 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3306 if (ret == NULL) {
3307 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3308 return (NULL);
3309 }
3310 ret->value = NULL;
3311 ret->next = NULL;
3312 return (ret);
3313}
3314
3315/**
3316 * xmlSchemaAddWildcard:
3317 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003318 * Adds a wildcard. It corresponds to a
3319 * xsd:anyAttribute and is used as storage for namespace
3320 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003321 *
3322 * Returns the new struture or NULL in case of error
3323 */
3324static xmlSchemaWildcardPtr
3325xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3326{
3327 xmlSchemaWildcardPtr ret = NULL;
3328
3329 if (ctxt == NULL)
3330 return (NULL);
3331
3332 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3333 if (ret == NULL) {
3334 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3335 return (NULL);
3336 }
3337 memset(ret, 0, sizeof(xmlSchemaWildcard));
3338 ret->minOccurs = 1;
3339 ret->maxOccurs = 1;
3340
3341 return (ret);
3342}
3343
Daniel Veillard4255d502002-04-16 15:50:10 +00003344/************************************************************************
3345 * *
3346 * Utilities for parsing *
3347 * *
3348 ************************************************************************/
3349
3350/**
3351 * xmlGetQNameProp:
3352 * @ctxt: a schema validation context
3353 * @node: a subtree containing XML Schema informations
3354 * @name: the attribute name
3355 * @namespace: the result namespace if any
3356 *
3357 * Extract a QName Attribute value
3358 *
3359 * Returns the NCName or NULL if not found, and also update @namespace
3360 * with the namespace URI
3361 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003362static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003363xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003364 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003365{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003366 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003367 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003368 const xmlChar *ret, *prefix;
3369 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003370 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003371
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003372 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003373 attr = xmlSchemaGetPropNode(node, name);
3374 if (attr == NULL)
3375 return (NULL);
3376 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003377
Daniel Veillard4255d502002-04-16 15:50:10 +00003378 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003379 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003380
Daniel Veillardba0153a2004-04-01 10:42:31 +00003381 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003382 ns = xmlSearchNs(node->doc, node, 0);
3383 if (ns) {
3384 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3385 return (val);
3386 }
3387 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003388 ret = xmlSplitQName3(val, &len);
3389 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003391 }
3392 ret = xmlDictLookup(ctxt->dict, ret, -1);
3393 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003394
3395 ns = xmlSearchNs(node->doc, node, prefix);
3396 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003397 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3398 NULL, NULL, (xmlNodePtr) attr,
3399 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003400 "The QName value '%s' has no corresponding namespace "
3401 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003402 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003403 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003404 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003406}
3407
3408/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003409 * xmlSchemaPValAttrNodeQNameValue:
3410 * @ctxt: a schema parser context
3411 * @schema: the schema context
3412 * @ownerDes: the designation of the parent element
3413 * @ownerItem: the parent as a schema object
3414 * @value: the QName value
3415 * @local: the resulting local part if found, the attribute value otherwise
3416 * @uri: the resulting namespace URI if found
3417 *
3418 * Extracts the local name and the URI of a QName value and validates it.
3419 * This one is intended to be used on attribute values that
3420 * should resolve to schema components.
3421 *
3422 * Returns 0, in case the QName is valid, a positive error code
3423 * if not valid and -1 if an internal error occurs.
3424 */
3425static int
3426xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3427 xmlSchemaPtr schema,
3428 xmlChar **ownerDes,
3429 xmlSchemaTypePtr ownerItem,
3430 xmlAttrPtr attr,
3431 const xmlChar *value,
3432 const xmlChar **uri,
3433 const xmlChar **prefix,
3434 const xmlChar **local)
3435{
3436 const xmlChar *pref;
3437 xmlNsPtr ns;
3438 int len, ret;
3439
3440 *uri = NULL;
3441 *local = NULL;
3442 if (prefix != 0)
3443 *prefix = NULL;
3444 ret = xmlValidateQName(value, 1);
3445 if (ret > 0) {
3446 xmlSchemaPSimpleTypeErr(ctxt,
3447 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3448 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003449 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3450 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003451 NULL, NULL, NULL);
3452 *local = value;
3453 return (ctxt->err);
3454 } else if (ret < 0)
3455 return (-1);
3456
3457 if (!strchr((char *) value, ':')) {
3458 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3459 if (ns)
3460 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3461 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3462 /*
3463 * This one takes care of included schemas with no
3464 * target namespace.
3465 */
3466 *uri = schema->targetNamespace;
3467 }
3468 *local = value;
3469 return (0);
3470 }
3471 /*
3472 * At this point xmlSplitQName3 has to return a local name.
3473 */
3474 *local = xmlSplitQName3(value, &len);
3475 *local = xmlDictLookup(ctxt->dict, *local, -1);
3476 pref = xmlDictLookup(ctxt->dict, value, len);
3477 if (prefix != 0)
3478 *prefix = pref;
3479 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3480 if (ns == NULL) {
3481 xmlSchemaPSimpleTypeErr(ctxt,
3482 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3483 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003484 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3485 "The QName value '%s' has no corresponding namespace "
3486 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003487 return (ctxt->err);
3488 } else {
3489 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3490 }
3491 return (0);
3492}
3493
3494/**
3495 * xmlSchemaPValAttrNodeQName:
3496 * @ctxt: a schema parser context
3497 * @schema: the schema context
3498 * @ownerDes: the designation of the owner element
3499 * @ownerItem: the owner as a schema object
3500 * @attr: the attribute node
3501 * @local: the resulting local part if found, the attribute value otherwise
3502 * @uri: the resulting namespace URI if found
3503 *
3504 * Extracts and validates the QName of an attribute value.
3505 * This one is intended to be used on attribute values that
3506 * should resolve to schema components.
3507 *
3508 * Returns 0, in case the QName is valid, a positive error code
3509 * if not valid and -1 if an internal error occurs.
3510 */
3511static int
3512xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3513 xmlSchemaPtr schema,
3514 xmlChar **ownerDes,
3515 xmlSchemaTypePtr ownerItem,
3516 xmlAttrPtr attr,
3517 const xmlChar **uri,
3518 const xmlChar **prefix,
3519 const xmlChar **local)
3520{
3521 const xmlChar *value;
3522
3523 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3524 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3525 ownerDes, ownerItem, attr, value, uri, prefix, local));
3526}
3527
3528/**
3529 * xmlSchemaPValAttrQName:
3530 * @ctxt: a schema parser context
3531 * @schema: the schema context
3532 * @ownerDes: the designation of the parent element
3533 * @ownerItem: the owner as a schema object
3534 * @ownerElem: the parent node of the attribute
3535 * @name: the name of the attribute
3536 * @local: the resulting local part if found, the attribute value otherwise
3537 * @uri: the resulting namespace URI if found
3538 *
3539 * Extracts and validates the QName of an attribute value.
3540 *
3541 * Returns 0, in case the QName is valid, a positive error code
3542 * if not valid and -1 if an internal error occurs.
3543 */
3544static int
3545xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3546 xmlSchemaPtr schema,
3547 xmlChar **ownerDes,
3548 xmlSchemaTypePtr ownerItem,
3549 xmlNodePtr ownerElem,
3550 const char *name,
3551 const xmlChar **uri,
3552 const xmlChar **prefix,
3553 const xmlChar **local)
3554{
3555 xmlAttrPtr attr;
3556
3557 attr = xmlSchemaGetPropNode(ownerElem, name);
3558 if (attr == NULL) {
3559 *local = NULL;
3560 *uri = NULL;
3561 return (0);
3562 }
3563 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3564 ownerDes, ownerItem, attr, uri, prefix, local));
3565}
3566
3567/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 * xmlGetMaxOccurs:
3569 * @ctxt: a schema validation context
3570 * @node: a subtree containing XML Schema informations
3571 *
3572 * Get the maxOccurs property
3573 *
3574 * Returns the default if not found, or the value
3575 */
3576static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003577xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3578 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003579{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003580 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003581 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003582 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003583
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003584 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3585 if (attr == NULL)
3586 return (def);
3587 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003588
3589 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003590 if (max != UNBOUNDED) {
3591 xmlSchemaPSimpleTypeErr(ctxt,
3592 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3593 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3594 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3595 val, NULL, NULL, NULL);
3596 return (def);
3597 } else
3598 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 }
3600
3601 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003602 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003603 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003604 if (*cur == 0) {
3605 xmlSchemaPSimpleTypeErr(ctxt,
3606 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3607 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3608 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3609 val, NULL, NULL, NULL);
3610 return (def);
3611 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 ret = ret * 10 + (*cur - '0');
3614 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 }
William M. Brack76e95df2003-10-18 16:20:14 +00003616 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003617 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003618 /*
3619 * TODO: Restrict the maximal value to Integer.
3620 */
3621 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3622 xmlSchemaPSimpleTypeErr(ctxt,
3623 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3624 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3625 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3626 val, NULL, NULL, NULL);
3627 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003628 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003629 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003630}
3631
3632/**
3633 * xmlGetMinOccurs:
3634 * @ctxt: a schema validation context
3635 * @node: a subtree containing XML Schema informations
3636 *
3637 * Get the minOccurs property
3638 *
3639 * Returns the default if not found, or the value
3640 */
3641static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003642xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3643 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003644{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003645 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003647 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003648
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003649 attr = xmlSchemaGetPropNode(node, "minOccurs");
3650 if (attr == NULL)
3651 return (def);
3652 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003653 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003654 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003655 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003656 if (*cur == 0) {
3657 xmlSchemaPSimpleTypeErr(ctxt,
3658 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3659 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3660 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3661 val, NULL, NULL, NULL);
3662 return (def);
3663 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003664 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 ret = ret * 10 + (*cur - '0');
3666 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 }
William M. Brack76e95df2003-10-18 16:20:14 +00003668 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003669 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003670 /*
3671 * TODO: Restrict the maximal value to Integer.
3672 */
3673 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3674 xmlSchemaPSimpleTypeErr(ctxt,
3675 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3676 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3677 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3678 val, NULL, NULL, NULL);
3679 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003680 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003681 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003682}
3683
3684/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003685 * xmlSchemaPGetBoolNodeValue:
3686 * @ctxt: a schema validation context
3687 * @ownerDes: owner designation
3688 * @ownerItem: the owner as a schema item
3689 * @node: the node holding the value
3690 *
3691 * Converts a boolean string value into 1 or 0.
3692 *
3693 * Returns 0 or 1.
3694 */
3695static int
3696xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3697 xmlChar **ownerDes,
3698 xmlSchemaTypePtr ownerItem,
3699 xmlNodePtr node)
3700{
3701 xmlChar *value = NULL;
3702 int res = 0;
3703
3704 value = xmlNodeGetContent(node);
3705 /*
3706 * 3.2.2.1 Lexical representation
3707 * An instance of a datatype that is defined as ·boolean·
3708 * can have the following legal literals {true, false, 1, 0}.
3709 */
3710 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3711 res = 1;
3712 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3713 res = 0;
3714 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3715 res = 1;
3716 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3717 res = 0;
3718 else {
3719 xmlSchemaPSimpleTypeErr(ctxt,
3720 XML_SCHEMAP_INVALID_BOOLEAN,
3721 ownerDes, ownerItem, node,
3722 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3723 "(1 | 0 | true | false)", BAD_CAST value,
3724 NULL, NULL, NULL);
3725 }
3726 if (value != NULL)
3727 xmlFree(value);
3728 return (res);
3729}
3730
3731/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003732 * xmlGetBooleanProp:
3733 * @ctxt: a schema validation context
3734 * @node: a subtree containing XML Schema informations
3735 * @name: the attribute name
3736 * @def: the default value
3737 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003738 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 *
3740 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003741 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003742 */
3743static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003744xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3745 xmlChar **ownerDes,
3746 xmlSchemaTypePtr ownerItem,
3747 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003748 const char *name, int def)
3749{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003750 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003751
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003752 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003753 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003755 /*
3756 * 3.2.2.1 Lexical representation
3757 * An instance of a datatype that is defined as ·boolean·
3758 * can have the following legal literals {true, false, 1, 0}.
3759 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003760 if (xmlStrEqual(val, BAD_CAST "true"))
3761 def = 1;
3762 else if (xmlStrEqual(val, BAD_CAST "false"))
3763 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003764 else if (xmlStrEqual(val, BAD_CAST "1"))
3765 def = 1;
3766 else if (xmlStrEqual(val, BAD_CAST "0"))
3767 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003769 xmlSchemaPSimpleTypeErr(ctxt,
3770 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003771 ownerDes, ownerItem, node,
3772 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3773 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003775 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003776}
3777
3778/************************************************************************
3779 * *
3780 * Shema extraction from an Infoset *
3781 * *
3782 ************************************************************************/
3783static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3784 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003785 xmlNodePtr node,
3786 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3788 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003790 xmlNodePtr node,
3791 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003792static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3793 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003794 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003795 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003796static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3797 xmlSchemaPtr schema,
3798 xmlNodePtr node);
3799static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3800 xmlSchemaPtr schema,
3801 xmlNodePtr node);
3802static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3803 ctxt,
3804 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003805 xmlNodePtr node,
3806 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003807static xmlSchemaAttributeGroupPtr
3808xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003809 xmlSchemaPtr schema, xmlNodePtr node,
3810 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003811static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3812 xmlSchemaPtr schema,
3813 xmlNodePtr node);
3814static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3815 xmlSchemaPtr schema,
3816 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003817static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003818xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3819 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003820
3821/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003822 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003823 *
3824 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003825 * @ownerDes: the designation of the parent element
3826 * @ownerItem: the schema object owner if existent
3827 * @attr: the schema attribute node being validated
3828 * @value: the value
3829 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003830 *
3831 * Validates a value against the given built-in type.
3832 * This one is intended to be used internally for validation
3833 * of schema attribute values during parsing of the schema.
3834 *
3835 * Returns 0 if the value is valid, a positive error code
3836 * number otherwise and -1 in case of an internal or API error.
3837 */
3838static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003839xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3840 xmlChar **ownerDes,
3841 xmlSchemaTypePtr ownerItem,
3842 xmlAttrPtr attr,
3843 const xmlChar *value,
3844 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003845{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003846
Daniel Veillardc0826a72004-08-10 14:17:33 +00003847 int ret = 0;
3848
3849 /*
3850 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3851 * one is really meant to be used internally, so better not.
3852 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003853 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003854 return (-1);
3855 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3856 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003857 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003858 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003859 "type '%s' is not a built-in type.\n",
3860 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003861 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003862 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003863 switch (type->builtInType) {
3864 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003865 case XML_SCHEMAS_QNAME:
3866 case XML_SCHEMAS_ANYURI:
3867 case XML_SCHEMAS_TOKEN:
3868 case XML_SCHEMAS_LANGUAGE:
3869 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
3870 break;
3871
3872 /*
3873 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003874 ret = xmlValidateNCName(value, 1);
3875 break;
3876 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003877 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003878 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003879 "Internal error: xmlSchemaPvalueAttrNode, use "
3880 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3881 "for extracting QName valueues instead.\n",
3882 NULL, NULL);
3883 return (-1);
3884 case XML_SCHEMAS_ANYURI:
3885 if (value != NULL) {
3886 xmlURIPtr uri = xmlParseURI((const char *) value);
3887 if (uri == NULL)
3888 ret = 1;
3889 else
3890 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003891 }
3892 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003893 case XML_SCHEMAS_TOKEN: {
3894 const xmlChar *cur = value;
3895
3896 if (IS_BLANK_CH(*cur)) {
3897 ret = 1;
3898 } else while (*cur != 0) {
3899 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3900 ret = 1;
3901 break;
3902 } else if (*cur == ' ') {
3903 cur++;
3904 if ((*cur == 0) || (*cur == ' ')) {
3905 ret = 1;
3906 break;
3907 }
3908 } else {
3909 cur++;
3910 }
3911 }
3912 }
3913 break;
3914 case XML_SCHEMAS_LANGUAGE:
3915 if (xmlCheckLanguageID(value) != 1)
3916 ret = 1;
3917 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003918 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003919 default: {
3920 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003921 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003922 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003923 "valueidation using the type '%s' is not implemented "
3924 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003925 type->name, NULL);
3926 return (-1);
3927 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003928 }
3929 /*
3930 * TODO: Should we use the S4S error codes instead?
3931 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003932 if (ret < 0) {
3933 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3934 XML_SCHEMAP_INTERNAL,
3935 "Internal error: xmlSchemaPValAttrNodeValue, "
3936 "failed to validate a schema attribute value.\n",
3937 NULL, NULL);
3938 return (-1);
3939 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003940 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3941 xmlSchemaPSimpleTypeErr(ctxt,
3942 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3943 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003944 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003945 NULL, NULL, NULL);
3946 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3947 } else {
3948 xmlSchemaPSimpleTypeErr(ctxt,
3949 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3950 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003951 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003952 NULL, NULL, NULL);
3953 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3954 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003955 }
3956 return (ret);
3957}
3958
3959/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003960 * xmlSchemaPValAttrNode:
3961 *
3962 * @ctxt: a schema parser context
3963 * @ownerDes: the designation of the parent element
3964 * @ownerItem: the schema object owner if existent
3965 * @attr: the schema attribute node being validated
3966 * @type: the built-in type to be validated against
3967 * @value: the resulting value if any
3968 *
3969 * Extracts and validates a value against the given built-in type.
3970 * This one is intended to be used internally for validation
3971 * of schema attribute values during parsing of the schema.
3972 *
3973 * Returns 0 if the value is valid, a positive error code
3974 * number otherwise and -1 in case of an internal or API error.
3975 */
3976static int
3977xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
3978 xmlChar **ownerDes,
3979 xmlSchemaTypePtr ownerItem,
3980 xmlAttrPtr attr,
3981 xmlSchemaTypePtr type,
3982 const xmlChar **value)
3983{
3984 const xmlChar *val;
3985
3986 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
3987 return (-1);
3988
3989 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3990 if (value != NULL)
3991 *value = val;
3992
3993 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
3994 val, type));
3995}
3996
3997/**
3998 * xmlSchemaPValAttr:
3999 *
4000 * @ctxt: a schema parser context
4001 * @node: the element node of the attribute
4002 * @ownerDes: the designation of the parent element
4003 * @ownerItem: the schema object owner if existent
4004 * @ownerElem: the owner element node
4005 * @name: the name of the schema attribute node
4006 * @type: the built-in type to be validated against
4007 * @value: the resulting value if any
4008 *
4009 * Extracts and validates a value against the given built-in type.
4010 * This one is intended to be used internally for validation
4011 * of schema attribute values during parsing of the schema.
4012 *
4013 * Returns 0 if the value is valid, a positive error code
4014 * number otherwise and -1 in case of an internal or API error.
4015 */
4016static int
4017xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4018 xmlChar **ownerDes,
4019 xmlSchemaTypePtr ownerItem,
4020 xmlNodePtr ownerElem,
4021 const char *name,
4022 xmlSchemaTypePtr type,
4023 const xmlChar **value)
4024{
4025 xmlAttrPtr attr;
4026
4027 if ((ctxt == NULL) || (type == NULL)) {
4028 if (value != NULL)
4029 *value = NULL;
4030 return (-1);
4031 }
4032 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4033 if (value != NULL)
4034 *value = NULL;
4035 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004036 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004037 "Internal error: xmlSchemaPValAttr, the given "
4038 "type '%s' is not a built-in type.\n",
4039 type->name, NULL);
4040 return (-1);
4041 }
4042 attr = xmlSchemaGetPropNode(ownerElem, name);
4043 if (attr == NULL) {
4044 if (value != NULL)
4045 *value = NULL;
4046 return (0);
4047 }
4048 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4049 type, value));
4050}
4051/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004052 * xmlSchemaParseAttrDecls:
4053 * @ctxt: a schema validation context
4054 * @schema: the schema being built
4055 * @node: a subtree containing XML Schema informations
4056 * @type: the hosting type
4057 *
4058 * parse a XML schema attrDecls declaration corresponding to
4059 * <!ENTITY % attrDecls
4060 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4061 */
4062static xmlNodePtr
4063xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4064 xmlNodePtr child, xmlSchemaTypePtr type)
4065{
4066 xmlSchemaAttributePtr lastattr, attr;
4067
4068 lastattr = NULL;
4069 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 (IS_SCHEMA(child, "attributeGroup"))) {
4071 attr = NULL;
4072 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004073 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004074 } else if (IS_SCHEMA(child, "attributeGroup")) {
4075 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004076 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004077 }
4078 if (attr != NULL) {
4079 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004080 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4081 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4082 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004083 type->attributes = attr;
4084 lastattr = attr;
4085 } else {
4086 lastattr->next = attr;
4087 lastattr = attr;
4088 }
4089 }
4090 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004091 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004092 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004093}
4094
4095/**
4096 * xmlSchemaParseAnnotation:
4097 * @ctxt: a schema validation context
4098 * @schema: the schema being built
4099 * @node: a subtree containing XML Schema informations
4100 *
4101 * parse a XML schema Attrribute declaration
4102 * *WARNING* this interface is highly subject to change
4103 *
William M. Bracke7091952004-05-11 15:09:58 +00004104 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004105 * 1 in case of success.
4106 */
4107static xmlSchemaAnnotPtr
4108xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4109 xmlNodePtr node)
4110{
4111 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004112 xmlNodePtr child = NULL;
4113 xmlAttrPtr attr;
4114 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004115
Daniel Veillardc0826a72004-08-10 14:17:33 +00004116 /*
4117 * INFO: S4S completed.
4118 */
4119 /*
4120 * id = ID
4121 * {any attributes with non-schema namespace . . .}>
4122 * Content: (appinfo | documentation)*
4123 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004124 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4125 return (NULL);
4126 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004127 attr = node->properties;
4128 while (attr != NULL) {
4129 if (((attr->ns == NULL) &&
4130 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4131 ((attr->ns != NULL) &&
4132 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4133
4134 xmlSchemaPIllegalAttrErr(ctxt,
4135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4136 NULL, NULL, attr);
4137 }
4138 attr = attr->next;
4139 }
4140 /* TODO: Check id. */
4141
4142 /*
4143 * And now for the children...
4144 */
4145 child = node->children;
4146 while (child != NULL) {
4147 if (IS_SCHEMA(child, "appinfo")) {
4148 /* TODO: make available the content of "appinfo". */
4149 /*
4150 * source = anyURI
4151 * {any attributes with non-schema namespace . . .}>
4152 * Content: ({any})*
4153 */
4154 attr = child->properties;
4155 while (attr != NULL) {
4156 if (((attr->ns == NULL) &&
4157 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4158 ((attr->ns != NULL) &&
4159 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004160
Daniel Veillardc0826a72004-08-10 14:17:33 +00004161 xmlSchemaPIllegalAttrErr(ctxt,
4162 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4163 NULL, NULL, attr);
4164 }
4165 attr = attr->next;
4166 }
4167 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4168 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4169 child = child->next;
4170 } else if (IS_SCHEMA(child, "documentation")) {
4171 /* TODO: make available the content of "documentation". */
4172 /*
4173 * source = anyURI
4174 * {any attributes with non-schema namespace . . .}>
4175 * Content: ({any})*
4176 */
4177 attr = child->properties;
4178 while (attr != NULL) {
4179 if (attr->ns == NULL) {
4180 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4181 xmlSchemaPIllegalAttrErr(ctxt,
4182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4183 NULL, NULL, attr);
4184 }
4185 } else {
4186 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4187 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4188 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4189
4190 xmlSchemaPIllegalAttrErr(ctxt,
4191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4192 NULL, NULL, attr);
4193 }
4194 }
4195 attr = attr->next;
4196 }
4197 /*
4198 * Attribute "xml:lang".
4199 */
4200 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4201 if (attr != NULL)
4202 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4203 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4204 child = child->next;
4205 } else {
4206 if (!barked)
4207 xmlSchemaPContentErr(ctxt,
4208 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4209 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4210 barked = 1;
4211 child = child->next;
4212 }
4213 }
4214
Daniel Veillard4255d502002-04-16 15:50:10 +00004215 return (ret);
4216}
4217
4218/**
4219 * xmlSchemaParseFacet:
4220 * @ctxt: a schema validation context
4221 * @schema: the schema being built
4222 * @node: a subtree containing XML Schema informations
4223 *
4224 * parse a XML schema Facet declaration
4225 * *WARNING* this interface is highly subject to change
4226 *
4227 * Returns the new type structure or NULL in case of error
4228 */
4229static xmlSchemaFacetPtr
4230xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004231 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004232{
4233 xmlSchemaFacetPtr facet;
4234 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004235 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004236
4237 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4238 return (NULL);
4239
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004240 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004241 if (facet == NULL) {
4242 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4243 return (NULL);
4244 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004245 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004246 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004247 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004248 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4249 "Facet %s has no value\n", node->name, NULL);
4250 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004251 return (NULL);
4252 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004253 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004254 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004255 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004256 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004257 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004258 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004259 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004261 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004262 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004263 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004264 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004265 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004266 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004267 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004268 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004269 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004270 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004272 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004274 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4275 } else if (IS_SCHEMA(node, "minLength")) {
4276 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4277 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4279 "Unknown facet type %s\n", node->name, NULL);
4280 xmlSchemaFreeFacet(facet);
4281 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004283 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004284 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004285 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4286 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4287 const xmlChar *fixed;
4288
4289 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4290 if (fixed != NULL) {
4291 if (xmlStrEqual(fixed, BAD_CAST "true"))
4292 facet->fixed = 1;
4293 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004294 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 child = node->children;
4296
4297 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004300 }
4301 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4303 "Facet %s has unexpected child content\n",
4304 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 }
4306 return (facet);
4307}
4308
4309/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 * xmlSchemaParseWildcardNs:
4311 * @ctxt: a schema parser context
4312 * @wildc: the wildcard, already created
4313 * @node: a subtree containing XML Schema informations
4314 *
4315 * Parses the attribute "processContents" and "namespace"
4316 * of a xsd:anyAttribute and xsd:any.
4317 * *WARNING* this interface is highly subject to change
4318 *
4319 * Returns 0 if everything goes fine, a positive error code
4320 * if something is not valid and -1 if an internal error occurs.
4321 */
4322static int
4323xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4324 xmlSchemaPtr schema,
4325 xmlSchemaWildcardPtr wildc,
4326 xmlNodePtr node)
4327{
4328 const xmlChar *pc, *ns, *dictnsItem;
4329 int ret = 0;
4330 xmlChar *nsItem;
4331 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4332 xmlAttrPtr attr;
4333
4334 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4335 if ((pc == NULL)
4336 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4337 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4338 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4339 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4340 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4341 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4342 } else {
4343 xmlSchemaPSimpleTypeErr(ctxt,
4344 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4345 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004346 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004347 NULL, NULL, NULL);
4348 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4349 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4350 }
4351 /*
4352 * Build the namespace constraints.
4353 */
4354 attr = xmlSchemaGetPropNode(node, "namespace");
4355 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4356 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4357 wildc->any = 1;
4358 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4359 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4360 if (wildc->negNsSet == NULL) {
4361 return (-1);
4362 }
4363 wildc->negNsSet->value = schema->targetNamespace;
4364 } else {
4365 const xmlChar *end, *cur;
4366
4367 cur = ns;
4368 do {
4369 while (IS_BLANK_CH(*cur))
4370 cur++;
4371 end = cur;
4372 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4373 end++;
4374 if (end == cur)
4375 break;
4376 nsItem = xmlStrndup(cur, end - cur);
4377 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4378 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4379 xmlSchemaPSimpleTypeErr(ctxt,
4380 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4381 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004382 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004383 "((##any | ##other) | List of (anyURI | "
4384 "(##targetNamespace | ##local)))",
4385 nsItem, NULL, NULL, NULL);
4386 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4387 } else {
4388 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4389 dictnsItem = schema->targetNamespace;
4390 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4391 dictnsItem = NULL;
4392 } else {
4393 /*
4394 * Validate the item (anyURI).
4395 */
4396 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4397 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4398 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4399 }
4400 /*
4401 * Avoid dublicate namespaces.
4402 */
4403 tmp = wildc->nsSet;
4404 while (tmp != NULL) {
4405 if (dictnsItem == tmp->value)
4406 break;
4407 tmp = tmp->next;
4408 }
4409 if (tmp == NULL) {
4410 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4411 if (tmp == NULL) {
4412 xmlFree(nsItem);
4413 return (-1);
4414 }
4415 tmp->value = dictnsItem;
4416 tmp->next = NULL;
4417 if (wildc->nsSet == NULL)
4418 wildc->nsSet = tmp;
4419 else
4420 lastNs->next = tmp;
4421 lastNs = tmp;
4422 }
4423
4424 }
4425 xmlFree(nsItem);
4426 cur = end;
4427 } while (*cur != 0);
4428 }
4429 return (ret);
4430}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004431
4432static int
4433xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4434 xmlSchemaTypePtr item,
4435 xmlNodePtr node,
4436 int minOccurs,
4437 int maxOccurs) {
4438
4439 if (maxOccurs != UNBOUNDED) {
4440 /*
4441 * TODO: Maby we should better not create the particle,
4442 * if min/max is invalid, since it could confuse the build of the
4443 * content model.
4444 */
4445 /*
4446 * 3.9.6 Schema Component Constraint: Particle Correct
4447 *
4448 */
4449 if (maxOccurs < 1) {
4450 /*
4451 * 2.2 {max occurs} must be greater than or equal to 1.
4452 */
4453 xmlSchemaPCustomAttrErr(ctxt,
4454 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4455 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4456 "The value must be greater than or equal to 1");
4457 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4458 } else if (minOccurs > maxOccurs) {
4459 /*
4460 * 2.1 {min occurs} must not be greater than {max occurs}.
4461 */
4462 xmlSchemaPCustomAttrErr(ctxt,
4463 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4464 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4465 "The value must not be greater than the value of 'maxOccurs'");
4466 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4467 }
4468 }
4469 return (0);
4470}
4471
Daniel Veillardc0826a72004-08-10 14:17:33 +00004472/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004473 * xmlSchemaParseAny:
4474 * @ctxt: a schema validation context
4475 * @schema: the schema being built
4476 * @node: a subtree containing XML Schema informations
4477 *
4478 * parse a XML schema Any declaration
4479 * *WARNING* this interface is highly subject to change
4480 *
4481 * Returns the new type structure or NULL in case of error
4482 */
4483static xmlSchemaTypePtr
4484xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4485 xmlNodePtr node)
4486{
4487 xmlSchemaTypePtr type;
4488 xmlNodePtr child = NULL;
4489 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004490 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004491 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004492
4493 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4494 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004495 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4496 "(nonNegativeInteger | unbounded)");
4497 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4498 "nonNegativeInteger");
4499 if ((minOccurs == 0) && (maxOccurs == 0))
4500 return (NULL);
4501
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004502 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004503 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004505 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004506 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004507 type->type = XML_SCHEMA_TYPE_ANY;
4508
Daniel Veillardc0826a72004-08-10 14:17:33 +00004509 wildc = xmlSchemaAddWildcard(ctxt);
4510 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004511 * Check min/max sanity.
4512 */
4513 type->maxOccurs = maxOccurs;
4514 type->minOccurs = minOccurs;
4515 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4516 node, type->minOccurs, type->maxOccurs);
4517 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004518 * This is not nice, since it is won't be used as a attribute wildcard,
4519 * but better than adding a field to the structure.
4520 */
4521 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004522 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004523 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004524 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004525 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4526 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004527 }
4528 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004529 xmlSchemaPErr2(ctxt, node, child,
4530 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4531 "Sequence %s has unexpected content\n", type->name,
4532 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 }
4534
4535 return (type);
4536}
4537
4538/**
4539 * xmlSchemaParseNotation:
4540 * @ctxt: a schema validation context
4541 * @schema: the schema being built
4542 * @node: a subtree containing XML Schema informations
4543 *
4544 * parse a XML schema Notation declaration
4545 *
4546 * Returns the new structure or NULL in case of error
4547 */
4548static xmlSchemaNotationPtr
4549xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004550 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004551{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004552 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 xmlSchemaNotationPtr ret;
4554 xmlNodePtr child = NULL;
4555
4556 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4557 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004558 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004560 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4561 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004562 return (NULL);
4563 }
4564 ret = xmlSchemaAddNotation(ctxt, schema, name);
4565 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 return (NULL);
4567 }
4568 child = node->children;
4569 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004570 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4571 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004572 }
4573 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004574 xmlSchemaPErr2(ctxt, node, child,
4575 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4576 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004577 }
4578
4579 return (ret);
4580}
4581
4582/**
4583 * xmlSchemaParseAnyAttribute:
4584 * @ctxt: a schema validation context
4585 * @schema: the schema being built
4586 * @node: a subtree containing XML Schema informations
4587 *
4588 * parse a XML schema AnyAttrribute declaration
4589 * *WARNING* this interface is highly subject to change
4590 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004591 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004593static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004594xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4595 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004596{
Daniel Veillard3646d642004-06-02 19:19:14 +00004597 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004599 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004600
4601 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4602 return (NULL);
4603
Daniel Veillard3646d642004-06-02 19:19:14 +00004604 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004605 if (ret == NULL) {
4606 return (NULL);
4607 }
William M. Bracke7091952004-05-11 15:09:58 +00004608 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004609 /*
4610 * Check for illegal attributes.
4611 */
4612 attr = node->properties;
4613 while (attr != NULL) {
4614 if (attr->ns == NULL) {
4615 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4616 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4617 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4618 xmlSchemaPIllegalAttrErr(ctxt,
4619 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4620 NULL, NULL, attr);
4621 }
4622 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4623 xmlSchemaPIllegalAttrErr(ctxt,
4624 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4625 NULL, NULL, attr);
4626 }
4627 attr = attr->next;
4628 }
4629 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4630 /*
4631 * Parse the namespace list.
4632 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004633 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4634 xmlSchemaFreeWildcard(ret);
4635 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004636 }
4637 /*
4638 * And now for the children...
4639 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004640 child = node->children;
4641 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4643 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 }
4645 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004646 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004647 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4648 NULL, NULL, node, child,
4649 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004650 }
4651
4652 return (ret);
4653}
4654
4655
4656/**
4657 * xmlSchemaParseAttribute:
4658 * @ctxt: a schema validation context
4659 * @schema: the schema being built
4660 * @node: a subtree containing XML Schema informations
4661 *
4662 * parse a XML schema Attrribute declaration
4663 * *WARNING* this interface is highly subject to change
4664 *
William M. Bracke7091952004-05-11 15:09:58 +00004665 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004666 */
4667static xmlSchemaAttributePtr
4668xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004669 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004670{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004671 const xmlChar *name, *attrValue;
4672 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004674 xmlNodePtr child = NULL;
4675 xmlAttrPtr attr, nameAttr;
4676 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004677
4678 /*
4679 * Note that the w3c spec assumes the schema to be validated with schema
4680 * for schemas beforehand.
4681 *
4682 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004683 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004684
4685 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4686 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004687 attr = xmlSchemaGetPropNode(node, "ref");
4688 nameAttr = xmlSchemaGetPropNode(node, "name");
4689
4690 if ((attr == NULL) && (nameAttr == NULL)) {
4691 /*
4692 * 3.2.3 : 3.1
4693 * One of ref or name must be present, but not both
4694 */
4695 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4696 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4697 "One of the attributes 'ref' or 'name' must be present");
4698 return (NULL);
4699 }
4700 if ((topLevel) || (attr == NULL)) {
4701 if (nameAttr == NULL) {
4702 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4703 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4704 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004705 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004706 }
4707 } else
4708 isRef = 1;
4709
4710 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004711 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004712 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4713
4714 /*
4715 * Parse as attribute reference.
4716 */
4717 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4718 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4719 &refPrefix, &ref) != 0) {
4720 return (NULL);
4721 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004722 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004723 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004724 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004725 if (ret == NULL) {
4726 if (repName != NULL)
4727 xmlFree(repName);
4728 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004729 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004730 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4731 ret->node = node;
4732 ret->refNs = refNs;
4733 ret->refPrefix = refPrefix;
4734 ret->ref = ref;
4735 /*
4736 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4737 */
4738 if (nameAttr != NULL)
4739 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4740 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4741 "ref", "name");
4742 /*
4743 * Check for illegal attributes.
4744 */
4745 attr = node->properties;
4746 while (attr != NULL) {
4747 if (attr->ns == NULL) {
4748 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4749 xmlStrEqual(attr->name, BAD_CAST "form")) {
4750 /*
4751 * 3.2.3 : 3.2
4752 * If ref is present, then all of <simpleType>,
4753 * form and type must be absent.
4754 */
4755 xmlSchemaPIllegalAttrErr(ctxt,
4756 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4757 (xmlSchemaTypePtr) ret, attr);
4758 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4759 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4760 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4761 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4762 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4763 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4764 xmlSchemaPIllegalAttrErr(ctxt,
4765 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4766 &repName, (xmlSchemaTypePtr) ret, attr);
4767 }
4768 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4769 xmlSchemaPIllegalAttrErr(ctxt,
4770 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4771 &repName, (xmlSchemaTypePtr) ret, attr);
4772 }
4773 attr = attr->next;
4774 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004775 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004776 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004777
4778 /*
4779 * Parse as attribute declaration.
4780 */
4781 if (xmlSchemaPValAttrNode(ctxt,
4782 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4783 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4784 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004785 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004786 /*
4787 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4788 */
4789 /*
4790 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4791 */
4792 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4793 xmlSchemaPSimpleTypeErr(ctxt,
4794 XML_SCHEMAP_NO_XMLNS,
4795 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004796 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004797 "The value must not match 'xmlns'",
4798 NULL, NULL);
4799 if (repName != NULL)
4800 xmlFree(repName);
4801 return (NULL);
4802 }
4803 /*
4804 * Evaluate the target namespace
4805 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004806 if (topLevel) {
4807 ns = schema->targetNamespace;
4808 } else {
4809 attr = xmlSchemaGetPropNode(node, "form");
4810 if (attr != NULL) {
4811 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4812 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4813 ns = schema->targetNamespace;
4814 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4815 xmlSchemaPSimpleTypeErr(ctxt,
4816 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4817 &repName, NULL, (xmlNodePtr) attr,
4818 NULL, "(qualified | unqualified)",
4819 attrValue, NULL, NULL, NULL);
4820 }
4821 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4822 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004823 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004824 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004825 if (ret == NULL) {
4826 if (repName != NULL)
4827 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004828 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004829 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004830 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4831 ret->node = node;
4832 if (topLevel)
4833 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4834 /*
4835 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4836 */
4837 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4838 xmlSchemaPCustomErr(ctxt,
4839 XML_SCHEMAP_NO_XSI,
4840 &repName, (xmlSchemaTypePtr) ret, node,
4841 "The target namespace must not match '%s'",
4842 xmlSchemaInstanceNs);
4843 }
4844 /*
4845 * Check for illegal attributes.
4846 */
4847 attr = node->properties;
4848 while (attr != NULL) {
4849 if (attr->ns == NULL) {
4850 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4851 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4852 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4853 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4854 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4855 if ((topLevel) ||
4856 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4857 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4858 xmlSchemaPIllegalAttrErr(ctxt,
4859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4860 &repName, (xmlSchemaTypePtr) ret, attr);
4861 }
4862 }
4863 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4864 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4865 &repName, (xmlSchemaTypePtr) ret, attr);
4866 }
4867 attr = attr->next;
4868 }
4869 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4870 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004871 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004872 /* TODO: Check ID. */
4873 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004874 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004875 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004876 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004877 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4878 if (ret->defValue != NULL)
4879 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4880 /*
4881 * Attribute "default".
4882 */
4883 attr = xmlSchemaGetPropNode(node, "default");
4884 if (attr != NULL) {
4885 /*
4886 * 3.2.3 : 1
4887 * default and fixed must not both be present.
4888 */
4889 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4890 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4891 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4892 } else
4893 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4894 }
4895 if (topLevel == 0) {
4896 /*
4897 * Attribute "use".
4898 */
4899 attr = xmlSchemaGetPropNode(node, "use");
4900 if (attr != NULL) {
4901 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4902 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4903 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4904 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4905 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4906 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4907 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4908 else
4909 xmlSchemaPSimpleTypeErr(ctxt,
4910 XML_SCHEMAP_INVALID_ATTR_USE,
4911 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004912 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004913 attrValue, NULL, NULL, NULL);
4914 } else
4915 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4916 /*
4917 * 3.2.3 : 2
4918 * If default and use are both present, use must have
4919 * the actual value optional.
4920 */
4921 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4922 (ret->defValue != NULL) &&
4923 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4924 xmlSchemaPSimpleTypeErr(ctxt,
4925 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4926 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004927 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004928 "The value must be 'optional' if the attribute "
4929 "'default' is present as well", NULL, NULL);
4930 }
4931 }
4932 /*
4933 * And now for the children...
4934 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004935 child = node->children;
4936 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004937 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4938 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004939 }
4940 if (isRef) {
4941 if (child != NULL) {
4942 if (IS_SCHEMA(child, "simpleType"))
4943 /*
4944 * 3.2.3 : 3.2
4945 * If ref is present, then all of <simpleType>,
4946 * form and type must be absent.
4947 */
4948 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4949 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4950 "(annotation?)");
4951 else
4952 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4953 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4954 "(annotation?)");
4955 }
4956 } else {
4957 if (IS_SCHEMA(child, "simpleType")) {
4958 if (ret->typeName != NULL) {
4959 /*
4960 * 3.2.3 : 4
4961 * type and <simpleType> must not both be present.
4962 */
4963 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4964 &repName, (xmlSchemaTypePtr) ret, node, child,
4965 "The attribute 'type' and the <simpleType> child "
4966 "are mutually exclusive", NULL);
4967 } else
4968 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
4969 child = child->next;
4970 }
4971 if (child != NULL)
4972 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4973 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4974 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004975 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 /*
4977 * Cleanup.
4978 */
4979 if (repName != NULL)
4980 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004981 return (ret);
4982}
4983
4984/**
4985 * xmlSchemaParseAttributeGroup:
4986 * @ctxt: a schema validation context
4987 * @schema: the schema being built
4988 * @node: a subtree containing XML Schema informations
4989 *
4990 * parse a XML schema Attribute Group declaration
4991 * *WARNING* this interface is highly subject to change
4992 *
4993 * Returns the attribute group or NULL in case of error.
4994 */
4995static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004996xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004997 xmlSchemaPtr schema, xmlNodePtr node,
4998 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004999{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005000 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005001 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005002 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005003 const xmlChar *oldcontainer;
5004 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005005
5006 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5007 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005008
5009 nameAttr = xmlSchemaGetPropNode(node, "name");
5010 attr = xmlSchemaGetPropNode(node, "ref");
5011 if ((topLevel) || (attr == NULL)) {
5012 /*
5013 * Parse as an attribute group definition.
5014 * Note that those are allowed at top level only.
5015 */
5016 if (nameAttr == NULL) {
5017 xmlSchemaPMissingAttrErr(ctxt,
5018 XML_SCHEMAP_S4S_ATTR_MISSING,
5019 NULL, NULL, node, "name", NULL);
5020 return (NULL);
5021 }
5022 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5023 /*
5024 * The name is crucial, exit if invalid.
5025 */
5026 if (xmlSchemaPValAttrNode(ctxt,
5027 NULL, NULL, nameAttr,
5028 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5029 return (NULL);
5030 }
5031 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5032 if (ret == NULL)
5033 return (NULL);
5034 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5035 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5036 ret->node = node;
5037 } else {
5038 char buf[50];
5039 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5040
5041 /*
5042 * Parse as an attribute group definition reference.
5043 */
5044 if (attr == NULL) {
5045 xmlSchemaPMissingAttrErr(ctxt,
5046 XML_SCHEMAP_S4S_ATTR_MISSING,
5047 NULL, NULL, node, "ref", NULL);
5048 }
5049 xmlSchemaPValAttrNodeQName(ctxt, schema,
5050 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5051
5052 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5053 name = (const xmlChar *) buf;
5054 if (name == NULL) {
5055 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5056 "attribute group definition reference", node);
5057 return (NULL);
5058 }
5059 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5060 if (ret == NULL)
5061 return (NULL);
5062 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5063 ret->ref = ref;
5064 ret->refNs = refNs;
5065 /* TODO: Is @refPrefix currently used? */
5066 ret->refPrefix = refPrefix;
5067 ret->node = node;
5068 }
5069 /*
5070 * Check for illegal attributes.
5071 */
5072 attr = node->properties;
5073 while (attr != NULL) {
5074 if (attr->ns == NULL) {
5075 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5076 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5077 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5078 {
5079 xmlSchemaPIllegalAttrErr(ctxt,
5080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5081 NULL, NULL, attr);
5082 }
5083 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5084 xmlSchemaPIllegalAttrErr(ctxt,
5085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5086 NULL, NULL, attr);
5087 }
5088 attr = attr->next;
5089 }
5090 /* TODO: Validate "id" ? */
5091 /*
5092 * And now for the children...
5093 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005095 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005096 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005097 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005098 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5099 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005100 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005101 if (topLevel) {
5102 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5103 if (IS_SCHEMA(child, "anyAttribute")) {
5104 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5105 child = child->next;
5106 }
5107 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005108 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005109 xmlSchemaPContentErr(ctxt,
5110 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5111 NULL, NULL, node, child, NULL,
5112 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005113 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005114 ctxt->container = oldcontainer;
5115 return (ret);
5116}
5117
5118/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005119 * xmlSchemaPValAttrFormDefault:
5120 * @value: the value
5121 * @flags: the flags to be modified
5122 * @flagQualified: the specific flag for "qualified"
5123 *
5124 * Returns 0 if the value is valid, 1 otherwise.
5125 */
5126static int
5127xmlSchemaPValAttrFormDefault(const xmlChar *value,
5128 int *flags,
5129 int flagQualified)
5130{
5131 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5132 if ((*flags & flagQualified) == 0)
5133 *flags |= flagQualified;
5134 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5135 return (1);
5136
5137 return (0);
5138}
5139
5140/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005141 * xmlSchemaPValAttrBlockFinal:
5142 * @value: the value
5143 * @flags: the flags to be modified
5144 * @flagAll: the specific flag for "#all"
5145 * @flagExtension: the specific flag for "extension"
5146 * @flagRestriction: the specific flag for "restriction"
5147 * @flagSubstitution: the specific flag for "substitution"
5148 * @flagList: the specific flag for "list"
5149 * @flagUnion: the specific flag for "union"
5150 *
5151 * Validates the value of the attribute "final" and "block". The value
5152 * is converted into the specified flag values and returned in @flags.
5153 *
5154 * Returns 0 if the value is valid, 1 otherwise.
5155 */
5156
5157static int
5158xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5159 int *flags,
5160 int flagAll,
5161 int flagExtension,
5162 int flagRestriction,
5163 int flagSubstitution,
5164 int flagList,
5165 int flagUnion)
5166{
5167 int ret = 0;
5168
5169 /*
5170 * TODO: This does not check for dublicate entries.
5171 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005172 if (value == NULL)
5173 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005174 if (xmlStrEqual(value, BAD_CAST "#all")) {
5175 if (flagAll != -1)
5176 *flags |= flagAll;
5177 else {
5178 if (flagExtension != -1)
5179 *flags |= flagExtension;
5180 if (flagRestriction != -1)
5181 *flags |= flagRestriction;
5182 if (flagSubstitution != -1)
5183 *flags |= flagSubstitution;
5184 if (flagList != -1)
5185 *flags |= flagList;
5186 if (flagUnion != -1)
5187 *flags |= flagUnion;
5188 }
5189 } else {
5190 const xmlChar *end, *cur = value;
5191 xmlChar *item;
5192
5193 do {
5194 while (IS_BLANK_CH(*cur))
5195 cur++;
5196 end = cur;
5197 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5198 end++;
5199 if (end == cur)
5200 break;
5201 item = xmlStrndup(cur, end - cur);
5202 if (xmlStrEqual(item, BAD_CAST "extension")) {
5203 if (flagExtension != -1) {
5204 if ((*flags & flagExtension) == 0)
5205 *flags |= flagExtension;
5206 } else
5207 ret = 1;
5208 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5209 if (flagRestriction != -1) {
5210 if ((*flags & flagRestriction) == 0)
5211 *flags |= flagRestriction;
5212 } else
5213 ret = 1;
5214 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5215 if (flagSubstitution != -1) {
5216 if ((*flags & flagSubstitution) == 0)
5217 *flags |= flagSubstitution;
5218 } else
5219 ret = 1;
5220 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5221 if (flagList != -1) {
5222 if ((*flags & flagList) == 0)
5223 *flags |= flagList;
5224 } else
5225 ret = 1;
5226 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5227 if (flagUnion != -1) {
5228 if ((*flags & flagUnion) == 0)
5229 *flags |= flagUnion;
5230 } else
5231 ret = 1;
5232 } else
5233 ret = 1;
5234 if (item != NULL)
5235 xmlFree(item);
5236 cur = end;
5237 } while ((ret == 0) && (*cur != 0));
5238 }
5239
5240 return (ret);
5241}
5242
5243/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005244 * xmlSchemaParseElement:
5245 * @ctxt: a schema validation context
5246 * @schema: the schema being built
5247 * @node: a subtree containing XML Schema informations
5248 *
5249 * parse a XML schema Element declaration
5250 * *WARNING* this interface is highly subject to change
5251 *
William M. Bracke7091952004-05-11 15:09:58 +00005252 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005253 */
5254static xmlSchemaElementPtr
5255xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005256 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005257{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005258 const xmlChar *name = NULL;
5259 const xmlChar *attrValue;
5260 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 xmlSchemaElementPtr ret;
5262 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005263 const xmlChar *oldcontainer;
5264 xmlAttrPtr attr, nameAttr;
5265 int minOccurs, maxOccurs;
5266 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005267
5268 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5269 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005270
Daniel Veillard4255d502002-04-16 15:50:10 +00005271 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5272 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005273
Daniel Veillardc0826a72004-08-10 14:17:33 +00005274 oldcontainer = ctxt->container;
5275
5276 nameAttr = xmlSchemaGetPropNode(node, "name");
5277 attr = xmlSchemaGetPropNode(node, "ref");
5278 if ((topLevel) || (attr == NULL)) {
5279 if (nameAttr == NULL) {
5280 xmlSchemaPMissingAttrErr(ctxt,
5281 XML_SCHEMAP_S4S_ATTR_MISSING,
5282 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5283 "name", NULL);
5284 return (NULL);
5285 }
5286 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5287 } else {
5288 isRef = 1;
5289
5290 }
5291 /*
5292 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5293 * to no component at all
5294 * TODO: It might be better to validate the element, even if it won't be
5295 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005296 */
5297 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5298 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005299 if ((minOccurs == 0) && (maxOccurs == 0))
5300 return (NULL);
5301 /*
5302 * If we get a "ref" attribute on a local <element> we will assume it's
5303 * a reference - even if there's a "name" attribute; this seems to be more
5304 * robust.
5305 */
5306 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005307 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005308 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5309
5310 /*
5311 * Parse as a particle.
5312 */
5313 xmlSchemaPValAttrNodeQName(ctxt, schema,
5314 (xmlChar **) &xmlSchemaElemDesAttrRef,
5315 NULL, attr, &refNs, &refPrefix, &ref);
5316
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005317 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005318 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005319 if (ret == NULL) {
5320 if (repName != NULL)
5321 xmlFree(repName);
5322 return (NULL);
5323 }
5324 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5325 ret->node = node;
5326 ret->ref = ref;
5327 ret->refNs = refNs;
5328 ret->refPrefix = refPrefix;
5329 ret->flags |= XML_SCHEMAS_ELEM_REF;
5330 /*
5331 * Check for illegal attributes.
5332 */
5333 /*
5334 * 3.3.3 : 2.1
5335 * One of ref or name must be present, but not both
5336 */
5337 if (nameAttr != NULL) {
5338 xmlSchemaPMutualExclAttrErr(ctxt,
5339 XML_SCHEMAP_SRC_ELEMENT_2_1,
5340 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5341 "ref", "name");
5342 }
5343 /* 3.3.3 : 2.2 */
5344 attr = node->properties;
5345 while (attr != NULL) {
5346 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005347 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5348 xmlStrEqual(attr->name, BAD_CAST "name") ||
5349 xmlStrEqual(attr->name, BAD_CAST "id") ||
5350 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5351 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5352 {
5353 attr = attr->next;
5354 continue;
5355 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005356 xmlSchemaPCustomAttrErr(ctxt,
5357 XML_SCHEMAP_SRC_ELEMENT_2_2,
5358 &repName, (xmlSchemaTypePtr) ret, attr,
5359 "Only the attributes 'minOccurs', 'maxOccurs' and "
5360 "'id' are allowed in addition to 'ref'");
5361 break;
5362 }
5363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5364 xmlSchemaPIllegalAttrErr(ctxt,
5365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5366 &repName, (xmlSchemaTypePtr) ret, attr);
5367 }
5368 attr = attr->next;
5369 }
5370 } else {
5371 const xmlChar *ns = NULL, *fixed;
5372
5373 /*
5374 * Parse as an element declaration.
5375 */
5376 if (xmlSchemaPValAttrNode(ctxt,
5377 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5378 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5379 return (NULL);
5380 /*
5381 * Evaluate the target namespace.
5382 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005383 if (topLevel) {
5384 ns = schema->targetNamespace;
5385 } else {
5386 attr = xmlSchemaGetPropNode(node, "form");
5387 if (attr != NULL) {
5388 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5389 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005390 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005391 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5392 xmlSchemaPSimpleTypeErr(ctxt,
5393 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5394 &repName, NULL, (xmlNodePtr) attr,
5395 NULL, "(qualified | unqualified)",
5396 attrValue, NULL, NULL, NULL);
5397 }
5398 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5399 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005400 }
5401 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005402 if (ret == NULL) {
5403 if (repName != NULL)
5404 xmlFree(repName);
5405 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005406 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005407 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5408 ret->node = node;
5409 /*
5410 * Check for illegal attributes.
5411 */
William M. Bracke7091952004-05-11 15:09:58 +00005412 attr = node->properties;
5413 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414 if (attr->ns == NULL) {
5415 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5417 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5418 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5419 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5420 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005421 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5422 {
5423 if (topLevel == 0) {
5424 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005425 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005426 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5427 {
5428 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5429 /*
5430 * 3.3.6 : 3 If there is a non-·absent· {substitution
5431 * group affiliation}, then {scope} must be global.
5432 * TODO: This one is redundant, since the S4S does
5433 * prohibit this attribute on local declarations already;
5434 * so why an explicit error code? Weird spec.
5435 * TODO: Move this to the proper constraint layer.
5436 * TODO: Or better wait for spec 1.1 to come.
5437 */
5438 xmlSchemaPIllegalAttrErr(ctxt,
5439 XML_SCHEMAP_E_PROPS_CORRECT_3,
5440 &repName, (xmlSchemaTypePtr) ret, attr);
5441 } else {
5442 xmlSchemaPIllegalAttrErr(ctxt,
5443 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5444 &repName, (xmlSchemaTypePtr) ret, attr);
5445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005446 }
5447 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5448 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5449 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5450
5451 xmlSchemaPIllegalAttrErr(ctxt,
5452 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5453 &repName, (xmlSchemaTypePtr) ret, attr);
5454 }
5455 }
5456 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5457
5458 xmlSchemaPIllegalAttrErr(ctxt,
5459 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5460 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005461 }
5462 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005463 }
William M. Bracke7091952004-05-11 15:09:58 +00005464 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005465 * Extract/validate attributes.
5466 */
5467 if (topLevel) {
5468 /*
5469 * Process top attributes of global element declarations here.
5470 */
5471 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5472 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5473 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5474 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5475 &(ret->substGroupNs), NULL, &(ret->substGroup));
5476 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5477 node, "abstract", 0))
5478 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5479 /*
5480 * Attribute "final".
5481 */
5482 attr = xmlSchemaGetPropNode(node, "final");
5483 if (attr == NULL) {
5484 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5485 } else {
5486 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5487 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5488 -1,
5489 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5490 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5491 xmlSchemaPSimpleTypeErr(ctxt,
5492 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5493 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005494 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005495 attrValue, NULL, NULL, NULL);
5496 }
5497 }
5498 }
5499 /*
5500 * Attribute "block".
5501 */
5502 attr = xmlSchemaGetPropNode(node, "block");
5503 if (attr == NULL) {
5504 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5505 } else {
5506 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5507 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5508 -1,
5509 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5510 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5511 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5512 xmlSchemaPSimpleTypeErr(ctxt,
5513 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5514 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005515 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005516 "restriction | substitution))", attrValue,
5517 NULL, NULL, NULL);
5518 }
5519 }
5520 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5521 node, "nillable", 0))
5522 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005523
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524 xmlSchemaPValAttrQName(ctxt, schema,
5525 &repName, (xmlSchemaTypePtr) ret, node,
5526 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005527
Daniel Veillardc0826a72004-08-10 14:17:33 +00005528 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5529 attr = xmlSchemaGetPropNode(node, "fixed");
5530 if (attr != NULL) {
5531 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5532 if (ret->value != NULL) {
5533 /*
5534 * 3.3.3 : 1
5535 * default and fixed must not both be present.
5536 */
5537 xmlSchemaPMutualExclAttrErr(ctxt,
5538 XML_SCHEMAP_SRC_ELEMENT_1,
5539 &repName, (xmlSchemaTypePtr) ret, attr,
5540 "default", "fixed");
5541 } else {
5542 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5543 ret->value = fixed;
5544 }
5545 }
5546 }
5547 /*
5548 * Extract/validate common attributes.
5549 */
5550 /* TODO: Check ID: */
5551 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5552 ret->minOccurs = minOccurs;
5553 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005554 if (topLevel != 1)
5555 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5556 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005557 /*
5558 * And now for the children...
5559 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005560 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005561 child = node->children;
5562 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5564 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005565 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005566 if (isRef) {
5567 if (child != NULL) {
5568 xmlSchemaPContentErr(ctxt,
5569 XML_SCHEMAP_SRC_ELEMENT_2_2,
5570 &repName, (xmlSchemaTypePtr) ret, node, child,
5571 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005572 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005574 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575 /*
5576 * 3.3.3 : 3
5577 * "type" and either <simpleType> or <complexType> are mutually
5578 * exclusive
5579 */
William M. Bracke7091952004-05-11 15:09:58 +00005580 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005581 xmlSchemaPContentErr(ctxt,
5582 XML_SCHEMAP_SRC_ELEMENT_3,
5583 &repName, (xmlSchemaTypePtr) ret, node, child,
5584 "The attribute 'type' and the <complexType> child are "
5585 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005586 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005587 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005588 child = child->next;
5589 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 /*
5591 * 3.3.3 : 3
5592 * "type" and either <simpleType> or <complexType> are
5593 * mutually exclusive
5594 */
William M. Bracke7091952004-05-11 15:09:58 +00005595 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 xmlSchemaPContentErr(ctxt,
5597 XML_SCHEMAP_SRC_ELEMENT_3,
5598 &repName, (xmlSchemaTypePtr) ret, node, child,
5599 "The attribute 'type' and the <simpleType> child are "
5600 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005601 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005602 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005603 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005604 }
William M. Bracke7091952004-05-11 15:09:58 +00005605 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005606 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005607 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005608 }
5609 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005610 xmlSchemaPContentErr(ctxt,
5611 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5612 &repName, (xmlSchemaTypePtr) ret, node, child,
5613 NULL, "(annotation?, ((simpleType | complexType)?, "
5614 "(unique | key | keyref)*))");
5615 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005616
Daniel Veillardc0826a72004-08-10 14:17:33 +00005617 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005618 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005619 /*
5620 * Cleanup.
5621 */
5622 if (repName != NULL)
5623 xmlFree(repName);
5624 /*
5625 * NOTE: Element Declaration Representation OK 4. will be checked at a
5626 * different layer.
5627 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005628 return (ret);
5629}
5630
5631/**
5632 * xmlSchemaParseUnion:
5633 * @ctxt: a schema validation context
5634 * @schema: the schema being built
5635 * @node: a subtree containing XML Schema informations
5636 *
5637 * parse a XML schema Union definition
5638 * *WARNING* this interface is highly subject to change
5639 *
William M. Bracke7091952004-05-11 15:09:58 +00005640 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005641 * 1 in case of success.
5642 */
5643static xmlSchemaTypePtr
5644xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005646{
5647 xmlSchemaTypePtr type, subtype, last = NULL;
5648 xmlNodePtr child = NULL;
5649 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005650 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005651
5652 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5653 return (NULL);
5654
William M. Brack2f2a6632004-08-20 23:09:47 +00005655 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5656 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005657 if (type == NULL)
5658 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005659 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005661 /*
5662 * Check for illegal attributes.
5663 */
5664 attr = node->properties;
5665 while (attr != NULL) {
5666 if (attr->ns == NULL) {
5667 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5668 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5669 xmlSchemaPIllegalAttrErr(ctxt,
5670 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5671 NULL, type, attr);
5672 }
5673 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5674 xmlSchemaPIllegalAttrErr(ctxt,
5675 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5676 NULL, type, attr);
5677 }
5678 attr = attr->next;
5679 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005680 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005681 /*
5682 * Attribute "memberTypes". This is a list of QNames.
5683 * TODO: Validate the QNames.
5684 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005685 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005686 /*
5687 * And now for the children...
5688 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005689 child = node->children;
5690 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005691 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5692 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005693 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005694 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005695 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005696 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005697 if (subtype != NULL) {
5698 if (last == NULL) {
5699 type->subtypes = subtype;
5700 last = subtype;
5701 } else {
5702 last->next = subtype;
5703 last = subtype;
5704 }
5705 last->next = NULL;
5706 }
5707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005708 }
5709 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005710 /* TODO: Think about the error code. */
5711 xmlSchemaPContentErr(ctxt,
5712 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5713 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005714 }
5715 return (type);
5716}
5717
5718/**
5719 * xmlSchemaParseList:
5720 * @ctxt: a schema validation context
5721 * @schema: the schema being built
5722 * @node: a subtree containing XML Schema informations
5723 *
5724 * parse a XML schema List definition
5725 * *WARNING* this interface is highly subject to change
5726 *
William M. Bracke7091952004-05-11 15:09:58 +00005727 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005728 * 1 in case of success.
5729 */
5730static xmlSchemaTypePtr
5731xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005732 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005733{
5734 xmlSchemaTypePtr type, subtype;
5735 xmlNodePtr child = NULL;
5736 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005737 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005738
5739 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5740 return (NULL);
5741
William M. Brack2f2a6632004-08-20 23:09:47 +00005742 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5743 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005744 if (type == NULL)
5745 return (NULL);
5746 type->node = node;
5747 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005748 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005749 /*
5750 * Check for illegal attributes.
5751 */
5752 attr = node->properties;
5753 while (attr != NULL) {
5754 if (attr->ns == NULL) {
5755 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5756 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5757 xmlSchemaPIllegalAttrErr(ctxt,
5758 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5759 NULL, type, attr);
5760 }
5761 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5762 xmlSchemaPIllegalAttrErr(ctxt,
5763 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5764 NULL, type, attr);
5765 }
5766 attr = attr->next;
5767 }
5768 /*
5769 * Attribute "itemType".
5770 */
5771 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5772 node, "itemType", &(type->baseNs), NULL, &(type->base));
5773 /*
5774 * And now for the children...
5775 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005776 child = node->children;
5777 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005778 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5779 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005780 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005781 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005782 if (IS_SCHEMA(child, "simpleType")) {
5783 if (type->base != NULL) {
5784 xmlSchemaPCustomErr(ctxt,
5785 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5786 NULL, type, node,
5787 "The attribute 'itemType' and the <simpleType> child "
5788 "are mutually exclusive", NULL);
5789 } else {
5790 subtype = (xmlSchemaTypePtr)
5791 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5792 type->subtypes = subtype;
5793 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005794 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005795 }
5796 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005797 /* TODO: Think about the error code. */
5798 xmlSchemaPContentErr(ctxt,
5799 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5800 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 }
5802 return (type);
5803}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804
Daniel Veillard4255d502002-04-16 15:50:10 +00005805/**
5806 * xmlSchemaParseSimpleType:
5807 * @ctxt: a schema validation context
5808 * @schema: the schema being built
5809 * @node: a subtree containing XML Schema informations
5810 *
5811 * parse a XML schema Simple Type definition
5812 * *WARNING* this interface is highly subject to change
5813 *
William M. Bracke7091952004-05-11 15:09:58 +00005814 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 */
5817static xmlSchemaTypePtr
5818xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005819 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005820{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005821 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005822 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005823 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005824 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005825 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005826
5827 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5828 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005829
Daniel Veillardc0826a72004-08-10 14:17:33 +00005830 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005831 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005832 if (attr == NULL) {
5833 xmlSchemaPMissingAttrErr(ctxt,
5834 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005835 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005836 "name", NULL);
5837 return (NULL);
5838 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005839 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005840 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005841 return (NULL);
5842 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005843 }
5844
5845 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005846 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005847
Daniel Veillard01fa6152004-06-29 17:04:39 +00005848 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005849 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005850 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005851 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005852 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005853 if (type == NULL)
5854 return (NULL);
5855 type->node = node;
5856 type->type = XML_SCHEMA_TYPE_SIMPLE;
5857 /*
5858 * Check for illegal attributes.
5859 */
5860 attr = node->properties;
5861 while (attr != NULL) {
5862 if (attr->ns == NULL) {
5863 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5864 xmlSchemaPIllegalAttrErr(ctxt,
5865 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005866 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005867 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005868 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5869 xmlSchemaPIllegalAttrErr(ctxt,
5870 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005871 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005872 }
5873 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005874 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005875 } else {
5876 /*
5877 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005878 *
5879 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005881 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 if (type == NULL)
5883 return (NULL);
5884 type->node = node;
5885 type->type = XML_SCHEMA_TYPE_SIMPLE;
5886 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5887 /*
5888 * Check for illegal attributes.
5889 */
5890 attr = node->properties;
5891 while (attr != NULL) {
5892 if (attr->ns == NULL) {
5893 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5894 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005895 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005896 xmlSchemaPIllegalAttrErr(ctxt,
5897 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005898 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005899 }
5900 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5901 xmlSchemaPIllegalAttrErr(ctxt,
5902 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005903 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005904 }
5905 attr = attr->next;
5906 }
5907 /*
5908 * Attribute "final".
5909 */
5910 attr = xmlSchemaGetPropNode(node, "final");
5911 if (attr == NULL) {
5912 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5913 } else {
5914 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5915 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5916 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5917 XML_SCHEMAS_TYPE_FINAL_LIST,
5918 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5919
5920 xmlSchemaPSimpleTypeErr(ctxt,
5921 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005922 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005923 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 attrValue, NULL, NULL, NULL);
5925 }
5926 }
5927 }
5928 /* TODO: Check id. */
5929 type->id = xmlSchemaGetProp(ctxt, node, "id");
5930 /*
5931 * And now for the children...
5932 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005933 oldCtxtType = ctxt->ctxtType;
5934 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005935 ctxt->ctxtType = type;
5936 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005937 child = node->children;
5938 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005939 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5940 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005941 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005942 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005943 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005944 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005945 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005946 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005947 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005948 subtype = (xmlSchemaTypePtr)
5949 xmlSchemaParseList(ctxt, schema, child);
5950 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005951 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005952 subtype = (xmlSchemaTypePtr)
5953 xmlSchemaParseUnion(ctxt, schema, child);
5954 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005955 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005956 type->subtypes = subtype;
5957 if ((child != NULL) || (subtype == NULL)) {
5958 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005959 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005960 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005961 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005962 ctxt->parentItem = oldParentItem;
5963 ctxt->ctxtType = oldCtxtType;
5964 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005965
Daniel Veillard4255d502002-04-16 15:50:10 +00005966 return (type);
5967}
5968
5969
5970/**
5971 * xmlSchemaParseGroup:
5972 * @ctxt: a schema validation context
5973 * @schema: the schema being built
5974 * @node: a subtree containing XML Schema informations
5975 *
5976 * parse a XML schema Group definition
5977 * *WARNING* this interface is highly subject to change
5978 *
William M. Bracke7091952004-05-11 15:09:58 +00005979 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 * 1 in case of success.
5981 */
5982static xmlSchemaTypePtr
5983xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005984 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005985{
5986 xmlSchemaTypePtr type, subtype;
5987 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005988 const xmlChar *name;
5989 const xmlChar *ref = NULL, *refNs = NULL;
5990 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005991 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005992
5993 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5994 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005995 /*
5996 * TODO: Validate the element even if no item is created
5997 * (i.e. min/maxOccurs == 0).
5998 */
5999 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6000 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6001 if ((minOccurs == 0) && (maxOccurs == 0)) {
6002 return (NULL);
6003 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006004 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006005 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006006 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6007 if (ref == NULL) {
6008 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006009 XML_SCHEMAP_GROUP_NONAME_NOREF,
6010 "Group definition or particle: One of the attributes \"name\" "
6011 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006012 return (NULL);
6013 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006014 if (refNs == NULL)
6015 refNs = schema->targetNamespace;
6016 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
6017 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006018 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006019 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006020 if (type == NULL)
6021 return (NULL);
6022 type->node = node;
6023 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006024 if (topLevel)
6025 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006026 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006027 type->ref = ref;
6028 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006029 type->minOccurs = minOccurs;
6030 type->maxOccurs = maxOccurs;
6031 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006032 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006033
6034 child = node->children;
6035 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006036 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6037 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006038 }
6039 subtype = NULL;
6040 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006041 subtype = (xmlSchemaTypePtr)
6042 xmlSchemaParseAll(ctxt, schema, child);
6043 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006045 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6046 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006047 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 subtype = (xmlSchemaTypePtr)
6049 xmlSchemaParseSequence(ctxt, schema, child);
6050 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 }
6052 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006053 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006054 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006055 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006056 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006057 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006058 }
6059
6060 return (type);
6061}
6062
6063/**
6064 * xmlSchemaParseAll:
6065 * @ctxt: a schema validation context
6066 * @schema: the schema being built
6067 * @node: a subtree containing XML Schema informations
6068 *
6069 * parse a XML schema All definition
6070 * *WARNING* this interface is highly subject to change
6071 *
William M. Bracke7091952004-05-11 15:09:58 +00006072 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006073 * 1 in case of success.
6074 */
6075static xmlSchemaTypePtr
6076xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006077 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006078{
6079 xmlSchemaTypePtr type, subtype, last = NULL;
6080 xmlNodePtr child = NULL;
6081 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006082 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006083
6084 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6085 return (NULL);
6086
6087
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006089 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006090 if (type == NULL)
6091 return (NULL);
6092 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006093 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006094 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006095
6096 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6097 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006098
6099 oldcontainer = ctxt->container;
6100 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 child = node->children;
6102 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006103 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6104 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006105 }
6106 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006107 subtype = (xmlSchemaTypePtr)
6108 xmlSchemaParseElement(ctxt, schema, child, 0);
6109 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006110 if (subtype->minOccurs > 1)
6111 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006112 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006113 NULL, NULL);
6114 if (subtype->maxOccurs > 1)
6115 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006116 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006117 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006118 if (last == NULL) {
6119 type->subtypes = subtype;
6120 last = subtype;
6121 } else {
6122 last->next = subtype;
6123 last = subtype;
6124 }
6125 last->next = NULL;
6126 }
6127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006128 }
6129 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006131 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006132 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006133 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006134 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006135 return (type);
6136}
6137
6138/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006139 * xmlSchemaCleanupDoc:
6140 * @ctxt: a schema validation context
6141 * @node: the root of the document.
6142 *
6143 * removes unwanted nodes in a schemas document tree
6144 */
6145static void
6146xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6147{
6148 xmlNodePtr delete, cur;
6149
6150 if ((ctxt == NULL) || (root == NULL)) return;
6151
6152 /*
6153 * Remove all the blank text nodes
6154 */
6155 delete = NULL;
6156 cur = root;
6157 while (cur != NULL) {
6158 if (delete != NULL) {
6159 xmlUnlinkNode(delete);
6160 xmlFreeNode(delete);
6161 delete = NULL;
6162 }
6163 if (cur->type == XML_TEXT_NODE) {
6164 if (IS_BLANK_NODE(cur)) {
6165 if (xmlNodeGetSpacePreserve(cur) != 1) {
6166 delete = cur;
6167 }
6168 }
6169 } else if ((cur->type != XML_ELEMENT_NODE) &&
6170 (cur->type != XML_CDATA_SECTION_NODE)) {
6171 delete = cur;
6172 goto skip_children;
6173 }
6174
6175 /*
6176 * Skip to next node
6177 */
6178 if (cur->children != NULL) {
6179 if ((cur->children->type != XML_ENTITY_DECL) &&
6180 (cur->children->type != XML_ENTITY_REF_NODE) &&
6181 (cur->children->type != XML_ENTITY_NODE)) {
6182 cur = cur->children;
6183 continue;
6184 }
6185 }
6186 skip_children:
6187 if (cur->next != NULL) {
6188 cur = cur->next;
6189 continue;
6190 }
6191
6192 do {
6193 cur = cur->parent;
6194 if (cur == NULL)
6195 break;
6196 if (cur == root) {
6197 cur = NULL;
6198 break;
6199 }
6200 if (cur->next != NULL) {
6201 cur = cur->next;
6202 break;
6203 }
6204 } while (cur != NULL);
6205 }
6206 if (delete != NULL) {
6207 xmlUnlinkNode(delete);
6208 xmlFreeNode(delete);
6209 delete = NULL;
6210 }
6211}
6212
William M. Brack2f2a6632004-08-20 23:09:47 +00006213
6214/**
6215 * xmlSchemaImportSchema
6216 *
6217 * @ctxt: a schema validation context
6218 * @schemaLocation: an URI defining where to find the imported schema
6219 *
6220 * import a XML schema
6221 * *WARNING* this interface is highly subject to change
6222 *
6223 * Returns -1 in case of error and 1 in case of success.
6224 */
6225#if 0
6226static xmlSchemaImportPtr
6227xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6228 const xmlChar *schemaLocation)
6229{
6230 xmlSchemaImportPtr import;
6231 xmlSchemaParserCtxtPtr newctxt;
6232
6233 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6234 if (newctxt == NULL) {
6235 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6236 NULL);
6237 return (NULL);
6238 }
6239 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6240 /* Keep the same dictionnary for parsing, really */
6241 xmlDictReference(ctxt->dict);
6242 newctxt->dict = ctxt->dict;
6243 newctxt->includes = 0;
6244 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6245
6246 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6247 ctxt->userData);
6248
6249 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6250 if (import == NULL) {
6251 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6252 NULL);
6253 xmlSchemaFreeParserCtxt(newctxt);
6254 return (NULL);
6255 }
6256
6257 memset(import, 0, sizeof(xmlSchemaImport));
6258 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6259 import->schema = xmlSchemaParse(newctxt);
6260
6261 if (import->schema == NULL) {
6262 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006263 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006264 "Failed to import schema from location \"%s\".\n",
6265 schemaLocation, NULL);
6266
6267 xmlSchemaFreeParserCtxt(newctxt);
6268 /* The schemaLocation is held by the dictionary.
6269 if (import->schemaLocation != NULL)
6270 xmlFree((xmlChar *)import->schemaLocation);
6271 */
6272 xmlFree(import);
6273 return NULL;
6274 }
6275
6276 xmlSchemaFreeParserCtxt(newctxt);
6277 return import;
6278}
6279#endif
6280
6281static void
6282xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6283{
6284 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6285 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6286
6287 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6288 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6289
6290 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6291 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6292 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6293 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6294 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6295 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6296 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6297 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6298
6299 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6300 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6301 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6302 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6303 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6304 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6305}
6306
6307static void
6308xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6309 xmlSchemaPtr schema,
6310 xmlNodePtr node)
6311{
6312 xmlAttrPtr attr;
6313 const xmlChar *val;
6314
6315 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6316 if (attr != NULL) {
6317 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6318 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6319 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6320 xmlSchemaPSimpleTypeErr(ctxt,
6321 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6322 NULL, NULL, (xmlNodePtr) attr, NULL,
6323 "(qualified | unqualified)", val, NULL, NULL, NULL);
6324 }
6325 }
6326
6327 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6328 if (attr != NULL) {
6329 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6330 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6331 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6332 xmlSchemaPSimpleTypeErr(ctxt,
6333 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6334 NULL, NULL, (xmlNodePtr) attr, NULL,
6335 "(qualified | unqualified)", val, NULL, NULL, NULL);
6336 }
6337 }
6338
6339 attr = xmlSchemaGetPropNode(node, "finalDefault");
6340 if (attr != NULL) {
6341 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6342 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6343 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6344 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6345 -1,
6346 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6347 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6348 xmlSchemaPSimpleTypeErr(ctxt,
6349 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6350 NULL, NULL, (xmlNodePtr) attr, NULL,
6351 "(#all | List of (extension | restriction | list | union))",
6352 val, NULL, NULL, NULL);
6353 }
6354 }
6355
6356 attr = xmlSchemaGetPropNode(node, "blockDefault");
6357 if (attr != NULL) {
6358 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6359 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6360 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6361 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6362 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6363 xmlSchemaPSimpleTypeErr(ctxt,
6364 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6365 NULL, NULL, (xmlNodePtr) attr, NULL,
6366 "(#all | List of (extension | restriction | substitution))",
6367 val, NULL, NULL, NULL);
6368 }
6369 }
6370}
6371
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006372/**
6373 * xmlSchemaParseSchemaTopLevel:
6374 * @ctxt: a schema validation context
6375 * @schema: the schemas
6376 * @nodes: the list of top level nodes
6377 *
6378 * Returns the internal XML Schema structure built from the resource or
6379 * NULL in case of error
6380 */
6381static void
6382xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6383 xmlSchemaPtr schema, xmlNodePtr nodes)
6384{
6385 xmlNodePtr child;
6386 xmlSchemaAnnotPtr annot;
6387
6388 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6389 return;
6390
6391 child = nodes;
6392 while ((IS_SCHEMA(child, "include")) ||
6393 (IS_SCHEMA(child, "import")) ||
6394 (IS_SCHEMA(child, "redefine")) ||
6395 (IS_SCHEMA(child, "annotation"))) {
6396 if (IS_SCHEMA(child, "annotation")) {
6397 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6398 if (schema->annot == NULL)
6399 schema->annot = annot;
6400 else
6401 xmlSchemaFreeAnnot(annot);
6402 } else if (IS_SCHEMA(child, "import")) {
6403 xmlSchemaParseImport(ctxt, schema, child);
6404 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006405 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006406 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006407 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006408 } else if (IS_SCHEMA(child, "redefine")) {
6409 TODO
6410 }
6411 child = child->next;
6412 }
6413 while (child != NULL) {
6414 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006415 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006416 child = child->next;
6417 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006418 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006419 child = child->next;
6420 } else if (IS_SCHEMA(child, "element")) {
6421 xmlSchemaParseElement(ctxt, schema, child, 1);
6422 child = child->next;
6423 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006424 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006425 child = child->next;
6426 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006427 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006428 child = child->next;
6429 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006430 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006431 child = child->next;
6432 } else if (IS_SCHEMA(child, "notation")) {
6433 xmlSchemaParseNotation(ctxt, schema, child);
6434 child = child->next;
6435 } else {
6436 xmlSchemaPErr2(ctxt, NULL, child,
6437 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006438 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006439 child->name, NULL);
6440 child = child->next;
6441 }
6442 while (IS_SCHEMA(child, "annotation")) {
6443 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6444 if (schema->annot == NULL)
6445 schema->annot = annot;
6446 else
6447 xmlSchemaFreeAnnot(annot);
6448 child = child->next;
6449 }
6450 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006451 ctxt->parentItem = NULL;
6452 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006453}
6454
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006455static xmlSchemaImportPtr
6456xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6457 xmlHashTablePtr *imports,
6458 const xmlChar *nsName)
6459{
6460 xmlSchemaImportPtr ret;
6461
6462 if (*imports == NULL) {
6463 *imports = xmlHashCreate(10);
6464 if (*imports == NULL) {
6465 xmlSchemaPCustomErr(ctxt,
6466 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6467 NULL, NULL, (xmlNodePtr) ctxt->doc,
6468 "Internal error: failed to build the import table",
6469 NULL);
6470 return (NULL);
6471 }
6472 }
6473 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6474 if (ret == NULL) {
6475 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6476 return (NULL);
6477 }
6478 memset(ret, 0, sizeof(xmlSchemaImport));
6479 if (nsName == NULL)
6480 nsName = XML_SCHEMAS_NO_NAMESPACE;
6481 xmlHashAddEntry(*imports, nsName, ret);
6482
6483 return (ret);
6484}
6485
6486static int
6487xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006488 xmlSchemaPtr schema,
6489 xmlNodePtr node,
6490 const xmlChar *nsName,
6491 const xmlChar *location,
6492 xmlDocPtr *doc,
6493 const xmlChar **targetNamespace,
6494 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006495{
6496 xmlParserCtxtPtr parserCtxt;
6497 xmlSchemaImportPtr import;
6498 const xmlChar *ns;
6499 xmlNodePtr root;
6500
6501 /*
6502 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6503 * <xsi:noNamespaceSchemaLocation>.
6504 */
6505 *doc = NULL;
6506 /*
6507 * Given that the schemaLocation [attribute] is only a hint, it is open
6508 * to applications to ignore all but the first <import> for a given
6509 * namespace, regardless of the ·actual value· of schemaLocation, but
6510 * such a strategy risks missing useful information when new
6511 * schemaLocations are offered.
6512 *
6513 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6514 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6515 * valid or not.
6516 * We will follow XSV here.
6517 */
6518 if (location == NULL) {
6519 /*
6520 * Schema Document Location Strategy:
6521 *
6522 * 3 Based on the namespace name, identify an existing schema document,
6523 * either as a resource which is an XML document or a <schema> element
6524 * information item, in some local schema repository;
6525 *
6526 * 5 Attempt to resolve the namespace name to locate such a resource.
6527 *
6528 * NOTE: Those stategies are not supported, so we will skip.
6529 */
6530 return (0);
6531 }
6532 if (nsName == NULL)
6533 ns = XML_SCHEMAS_NO_NAMESPACE;
6534 else
6535 ns = nsName;
6536
6537 import = xmlHashLookup(schema->schemasImports, ns);
6538 if (import != NULL) {
6539 /*
6540 * There was a valid resource for the specified namespace already
6541 * defined, so skip.
6542 * TODO: This might be changed someday to allow import of
6543 * components from multiple documents for a single target namespace.
6544 */
6545 return (0);
6546 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006547
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006548 /*
6549 * Schema Document Location Strategy:
6550 *
6551 * 2 Based on the location URI, identify an existing schema document,
6552 * either as a resource which is an XML document or a <schema> element
6553 * information item, in some local schema repository;
6554 *
6555 * 4 Attempt to resolve the location URI, to locate a resource on the
6556 * web which is or contains or references a <schema> element;
6557 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6558 *
6559 */
6560 if ((absolute == 0) && (node != NULL)) {
6561 xmlChar *base, *URI;
6562
6563 base = xmlNodeGetBase(node->doc, node);
6564 if (base == NULL) {
6565 URI = xmlBuildURI(location, node->doc->URL);
6566 } else {
6567 URI = xmlBuildURI(location, base);
6568 xmlFree(base);
6569 }
6570 if (URI != NULL) {
6571 location = xmlDictLookup(ctxt->dict, URI, -1);
6572 xmlFree(URI);
6573 }
6574 }
6575 parserCtxt = xmlNewParserCtxt();
6576 if (parserCtxt == NULL) {
6577 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6578 "allocating a parser context", NULL);
6579 return(-1);
6580 }
6581
6582 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6583 NULL, SCHEMAS_PARSE_OPTIONS);
6584
6585 /*
6586 * 2.1 The referent is (a fragment of) a resource which is an
6587 * XML document (see clause 1.1), which in turn corresponds to
6588 * a <schema> element information item in a well-formed information
6589 * set, which in turn corresponds to a valid schema.
6590 * TODO: What to do with the "fragment" stuff?
6591 *
6592 * 2.2 The referent is a <schema> element information item in
6593 * a well-formed information set, which in turn corresponds
6594 * to a valid schema.
6595 * NOTE: 2.2 won't apply, since only XML documents will be processed
6596 * here.
6597 */
6598 if (*doc == NULL) {
6599 xmlErrorPtr lerr;
6600 /*
6601 * It is *not* an error for the application schema reference
6602 * strategy to fail.
6603 *
6604 * If the doc is NULL and the parser error is an IO error we
6605 * will assume that the resource could not be located or accessed.
6606 *
6607 * TODO: Try to find specific error codes to react only on
6608 * localisation failures.
6609 *
6610 * TODO, FIXME: Check the spec: is a namespace added to the imported
6611 * namespaces, even if the schemaLocation did not provide
6612 * a resource? I guess so, since omitting the "schemaLocation"
6613 * attribute, imports a namespace as well.
6614 */
6615 lerr = xmlGetLastError();
6616 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6617 xmlFreeParserCtxt(parserCtxt);
6618 return(0);
6619 }
6620
6621 xmlSchemaPCustomErr(ctxt,
6622 XML_SCHEMAP_SRC_IMPORT_2_1,
6623 NULL, NULL, node,
6624 "Failed to parse the resource '%s' for import",
6625 location);
6626 xmlFreeParserCtxt(parserCtxt);
6627 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6628 }
6629 xmlFreeParserCtxt(parserCtxt);
6630
6631 root = xmlDocGetRootElement(*doc);
6632 if (root == NULL) {
6633 xmlSchemaPCustomErr(ctxt,
6634 XML_SCHEMAP_SRC_IMPORT_2_1,
6635 NULL, NULL, node,
6636 "The XML document '%s' to be imported has no document "
6637 "element", location);
6638 xmlFreeDoc(*doc);
6639 *doc = NULL;
6640 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6641 }
6642
6643 xmlSchemaCleanupDoc(ctxt, root);
6644
6645 if (!IS_SCHEMA(root, "schema")) {
6646 xmlSchemaPCustomErr(ctxt,
6647 XML_SCHEMAP_SRC_IMPORT_2_1,
6648 NULL, NULL, node,
6649 "The XML document '%s' to be imported is not a XML schema document",
6650 location);
6651 xmlFreeDoc(*doc);
6652 *doc = NULL;
6653 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6654 }
6655 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6656 /*
6657 * Schema Representation Constraint: Import Constraints and Semantics
6658 */
6659 if (nsName == NULL) {
6660 if (*targetNamespace != NULL) {
6661 xmlSchemaPCustomErr(ctxt,
6662 XML_SCHEMAP_SRC_IMPORT_3_2,
6663 NULL, NULL, node,
6664 "The XML schema to be imported is not expected "
6665 "to have a target namespace; this differs from "
6666 "its target namespace of '%s'", *targetNamespace);
6667 xmlFreeDoc(*doc);
6668 *doc = NULL;
6669 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6670 }
6671 } else {
6672 if (*targetNamespace == NULL) {
6673 xmlSchemaPCustomErr(ctxt,
6674 XML_SCHEMAP_SRC_IMPORT_3_1,
6675 NULL, NULL, node,
6676 "The XML schema to be imported is expected to have a target "
6677 "namespace of '%s'", nsName);
6678 xmlFreeDoc(*doc);
6679 *doc = NULL;
6680 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6681 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6682 xmlSchemaPCustomErrExt(ctxt,
6683 XML_SCHEMAP_SRC_IMPORT_3_1,
6684 NULL, NULL, node,
6685 "The XML schema to be imported is expected to have a "
6686 "target namespace of '%s'; this differs from "
6687 "its target namespace of '%s'",
6688 nsName, *targetNamespace, NULL);
6689 xmlFreeDoc(*doc);
6690 *doc = NULL;
6691 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6692 }
6693 }
6694
6695 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6696 if (import == NULL) {
6697 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6698 NULL, NULL, NULL,
6699 "Internal error: xmlSchemaAcquireSchemaDoc, "
6700 "failed to build import table", NULL);
6701 xmlFreeDoc(*doc);
6702 *doc = NULL;
6703 return (-1);
6704 }
6705 import->schemaLocation = location;
6706 import->doc = *doc;
6707 return (0);
6708}
William M. Brack2f2a6632004-08-20 23:09:47 +00006709
6710/**
6711 * xmlSchemaParseImport:
6712 * @ctxt: a schema validation context
6713 * @schema: the schema being built
6714 * @node: a subtree containing XML Schema informations
6715 *
6716 * parse a XML schema Import definition
6717 * *WARNING* this interface is highly subject to change
6718 *
6719 * Returns 0 in case of success, a positive error code if
6720 * not valid and -1 in case of an internal error.
6721 */
6722static int
6723xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6724 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006725{
6726 xmlNodePtr child;
6727 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006728 const xmlChar *schemaLocation = NULL;
6729 const xmlChar *targetNamespace, *oldTNS, *url;
6730 xmlAttrPtr attr;
6731 xmlDocPtr doc;
6732 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006733 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006734
6735
6736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6737 return (-1);
6738
6739 /*
6740 * Check for illegal attributes.
6741 */
6742 attr = node->properties;
6743 while (attr != NULL) {
6744 if (attr->ns == NULL) {
6745 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6746 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6747 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6748 xmlSchemaPIllegalAttrErr(ctxt,
6749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6750 NULL, NULL, attr);
6751 }
6752 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6753 xmlSchemaPIllegalAttrErr(ctxt,
6754 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6755 NULL, NULL, attr);
6756 }
6757 attr = attr->next;
6758 }
6759 /*
6760 * Extract and validate attributes.
6761 */
6762 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6763 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6764 &namespace) != 0) {
6765 xmlSchemaPSimpleTypeErr(ctxt,
6766 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6767 NULL, NULL, node,
6768 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6769 NULL, namespace, NULL, NULL, NULL);
6770 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6771 }
6772
6773 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6774 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6775 &schemaLocation) != 0) {
6776 xmlSchemaPSimpleTypeErr(ctxt,
6777 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6778 NULL, NULL, node,
6779 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6780 NULL, namespace, NULL, NULL, NULL);
6781 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6782 }
6783 /*
6784 * And now for the children...
6785 */
6786 child = node->children;
6787 if (IS_SCHEMA(child, "annotation")) {
6788 /*
6789 * the annotation here is simply discarded ...
6790 */
6791 child = child->next;
6792 }
6793 if (child != NULL) {
6794 xmlSchemaPContentErr(ctxt,
6795 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6796 NULL, NULL, node, child, NULL,
6797 "(annotation?)");
6798 }
6799 /*
6800 * Apply additional constraints.
6801 */
6802 if (namespace != NULL) {
6803 /*
6804 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6805 * must not match the ·actual value· of the enclosing <schema>'s
6806 * targetNamespace [attribute].
6807 */
6808 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6809 xmlSchemaPCustomErr(ctxt,
6810 XML_SCHEMAP_SRC_IMPORT_1_1,
6811 NULL, NULL, node,
6812 "The value of the attribute 'namespace' must not match "
6813 "the target namespace '%s' of the importing schema",
6814 schema->targetNamespace);
6815 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6816 }
6817 } else {
6818 /*
6819 * 1.2 If the namespace [attribute] is not present, then the enclosing
6820 * <schema> must have a targetNamespace [attribute].
6821 */
6822 if (schema->targetNamespace == NULL) {
6823 xmlSchemaPCustomErr(ctxt,
6824 XML_SCHEMAP_SRC_IMPORT_1_2,
6825 NULL, NULL, node,
6826 "The attribute 'namespace' must be existent if "
6827 "the importing schema has no target namespace",
6828 NULL);
6829 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6830 }
6831 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006832 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006833 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006834 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006835 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6836 schemaLocation, &doc, &targetNamespace, 0);
6837 if (ret != 0) {
6838 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006839 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006840 return (ret);
6841 } else if (doc != NULL) {
6842 /*
6843 * Save and reset the context & schema.
6844 */
6845 url = ctxt->URL;
6846 /* TODO: Is using the doc->URL here correct? */
6847 ctxt->URL = doc->URL;
6848 flags = schema->flags;
6849 oldTNS = schema->targetNamespace;
6850 /*
6851 * Parse the schema.
6852 */
6853 root = xmlDocGetRootElement(doc);
6854 xmlSchemaClearSchemaDefaults(schema);
6855 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6856 schema->targetNamespace = targetNamespace;
6857 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6858 /*
6859 * Restore the context & schema.
6860 */
6861 schema->flags = flags;
6862 schema->targetNamespace = oldTNS;
6863 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006864 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006865
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006866 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006867}
6868
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006869/**
6870 * xmlSchemaParseInclude:
6871 * @ctxt: a schema validation context
6872 * @schema: the schema being built
6873 * @node: a subtree containing XML Schema informations
6874 *
6875 * parse a XML schema Include definition
6876 *
William M. Bracke7091952004-05-11 15:09:58 +00006877 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006878 * 1 in case of success.
6879 */
6880static int
6881xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6882 xmlNodePtr node)
6883{
6884 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006886 xmlDocPtr doc;
6887 xmlNodePtr root;
6888 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006889 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006890 xmlAttrPtr attr;
6891 int saveFlags;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006892
6893
6894 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6895 return (-1);
6896
6897 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006898 * Check for illegal attributes.
6899 */
6900 attr = node->properties;
6901 while (attr != NULL) {
6902 if (attr->ns == NULL) {
6903 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6904 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6905 xmlSchemaPIllegalAttrErr(ctxt,
6906 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6907 NULL, NULL, attr);
6908 }
6909 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6910 xmlSchemaPIllegalAttrErr(ctxt,
6911 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6912 NULL, NULL, attr);
6913 }
6914 attr = attr->next;
6915 }
6916 /*
6917 * Extract and validate attributes.
6918 */
6919 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006920 * Preliminary step, extract the URI-Reference for the include and
6921 * make an URI from the base.
6922 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6924 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006925 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006926 xmlChar *uri = NULL;
6927
6928 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6929 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6930 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006931 base = xmlNodeGetBase(node->doc, node);
6932 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006933 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006934 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006935 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006936 xmlFree(base);
6937 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006938 if (uri != NULL) {
6939 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6940 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006941 }
6942 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006943 xmlSchemaPMissingAttrErr(ctxt,
6944 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6945 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006946 return (-1);
6947 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006948 /*
6949 * And now for the children...
6950 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006951 child = node->children;
6952 while (IS_SCHEMA(child, "annotation")) {
6953 /*
6954 * the annotations here are simply discarded ...
6955 */
6956 child = child->next;
6957 }
6958 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006959 xmlSchemaPContentErr(ctxt,
6960 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
6961 NULL, NULL, node, child, NULL,
6962 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006963 }
6964
6965 /*
6966 * First step is to parse the input document into an DOM/Infoset
6967 */
6968 doc = xmlReadFile((const char *) schemaLocation, NULL,
6969 SCHEMAS_PARSE_OPTIONS);
6970 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006971 /*
6972 * TODO: It is not an error for the ·actual value· of the
6973 * schemaLocation [attribute] to fail to resolve it all, in which
6974 * case no corresponding inclusion is performed.
6975 * So do we need a warning report here?
6976 */
6977 xmlSchemaPCustomErr(ctxt,
6978 XML_SCHEMAP_FAILED_LOAD,
6979 NULL, NULL, node,
6980 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006981 return(-1);
6982 }
6983
6984 /*
6985 * Then extract the root of the schema
6986 */
6987 root = xmlDocGetRootElement(doc);
6988 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006989 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006990 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00006991 NULL, NULL, node,
6992 "The included document '%s' has no document "
6993 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006994 xmlFreeDoc(doc);
6995 return (-1);
6996 }
6997
6998 /*
6999 * Remove all the blank text nodes
7000 */
7001 xmlSchemaCleanupDoc(ctxt, root);
7002
7003 /*
7004 * Check the schemas top level element
7005 */
7006 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007007 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007008 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007009 NULL, NULL, node,
7010 "The document '%s' to be included is not a schema document",
7011 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007012 xmlFreeDoc(doc);
7013 return (-1);
7014 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007015
William M. Brack2f2a6632004-08-20 23:09:47 +00007016 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007017 /*
7018 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7019 * value· is identical to the ·actual value· of the targetNamespace
7020 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7021 */
7022 if (targetNamespace != NULL) {
7023 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007024 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007025 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007026 NULL, NULL, node,
7027 "The target namespace of the included schema "
7028 "'%s' has to be absent, since the including schema "
7029 "has no target namespace",
7030 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007031 xmlFreeDoc(doc);
7032 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007033 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7034 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007035 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007036 NULL, NULL, node,
7037 "The target namespace '%s' of the included schema '%s' "
7038 "differs from '%s' of the including schema",
7039 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007040 xmlFreeDoc(doc);
7041 return (-1);
7042 }
7043 } else if (schema->targetNamespace != NULL) {
7044 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7045 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7046 } else
7047 wasConvertingNs = 1;
7048 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007049 /*
7050 * register the include
7051 */
7052 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7053 if (include == NULL) {
7054 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7055 xmlFreeDoc(doc);
7056 return (-1);
7057 }
7058
7059 memset(include, 0, sizeof(xmlSchemaInclude));
7060 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7061 include->doc = doc;
7062 include->next = schema->includes;
7063 schema->includes = include;
7064
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007065 /*
7066 * parse the declarations in the included file like if they
7067 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007068 */
7069 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007070 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007071 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007072 /*
7073 * The default values ("blockDefault", "elementFormDefault", etc.)
7074 * are set to the values of the included schema and restored afterwards.
7075 */
7076 saveFlags = schema->flags;
7077 xmlSchemaClearSchemaDefaults(schema);
7078 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007079 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007080 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007081 /*
7082 * Remove the converting flag.
7083 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007084 if ((wasConvertingNs == 0) &&
7085 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007086 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007087 return (1);
7088}
7089
7090/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007091 * xmlSchemaParseChoice:
7092 * @ctxt: a schema validation context
7093 * @schema: the schema being built
7094 * @node: a subtree containing XML Schema informations
7095 *
7096 * parse a XML schema Choice definition
7097 * *WARNING* this interface is highly subject to change
7098 *
William M. Bracke7091952004-05-11 15:09:58 +00007099 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007100 * 1 in case of success.
7101 */
7102static xmlSchemaTypePtr
7103xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007104 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007105{
7106 xmlSchemaTypePtr type, subtype, last = NULL;
7107 xmlNodePtr child = NULL;
7108 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007109 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007110 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007111
7112 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7113 return (NULL);
7114
7115
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007116 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007117 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007118 if (type == NULL)
7119 return (NULL);
7120 type->node = node;
7121 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007122 /*
7123 * Check for illegal attributes.
7124 */
7125 attr = node->properties;
7126 while (attr != NULL) {
7127 if (attr->ns == NULL) {
7128 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7129 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7130 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7131 xmlSchemaPIllegalAttrErr(ctxt,
7132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7133 NULL, type, attr);
7134 }
7135 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7136 xmlSchemaPIllegalAttrErr(ctxt,
7137 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7138 NULL, type, attr);
7139 }
7140 attr = attr->next;
7141 }
7142 /*
7143 * Extract and validate attributes.
7144 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007145 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007146 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7147 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7148 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007149 /*
7150 * And now for the children...
7151 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007152 oldcontainer = ctxt->container;
7153 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007154 child = node->children;
7155 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007156 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7157 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007158 }
7159 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007160 (IS_SCHEMA(child, "group")) ||
7161 (IS_SCHEMA(child, "any")) ||
7162 (IS_SCHEMA(child, "choice")) ||
7163 (IS_SCHEMA(child, "sequence"))) {
7164 subtype = NULL;
7165 if (IS_SCHEMA(child, "element")) {
7166 subtype = (xmlSchemaTypePtr)
7167 xmlSchemaParseElement(ctxt, schema, child, 0);
7168 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007169 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007170 } else if (IS_SCHEMA(child, "any")) {
7171 subtype = xmlSchemaParseAny(ctxt, schema, child);
7172 } else if (IS_SCHEMA(child, "sequence")) {
7173 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7174 } else if (IS_SCHEMA(child, "choice")) {
7175 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7176 }
7177 if (subtype != NULL) {
7178 if (last == NULL) {
7179 type->subtypes = subtype;
7180 last = subtype;
7181 } else {
7182 last->next = subtype;
7183 last = subtype;
7184 }
7185 last->next = NULL;
7186 }
7187 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007188 }
7189 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007190 /* TODO: error code. */
7191 xmlSchemaPContentErr(ctxt,
7192 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7193 NULL, type, node, child, NULL,
7194 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007195 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007196 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007197 return (type);
7198}
7199
7200/**
7201 * xmlSchemaParseSequence:
7202 * @ctxt: a schema validation context
7203 * @schema: the schema being built
7204 * @node: a subtree containing XML Schema informations
7205 *
7206 * parse a XML schema Sequence definition
7207 * *WARNING* this interface is highly subject to change
7208 *
William M. Bracke7091952004-05-11 15:09:58 +00007209 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007210 * 1 in case of success.
7211 */
7212static xmlSchemaTypePtr
7213xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007214 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007215{
7216 xmlSchemaTypePtr type, subtype, last = NULL;
7217 xmlNodePtr child = NULL;
7218 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007219 xmlAttrPtr attr;
7220 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221
7222 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7223 return (NULL);
7224
William M. Brack2f2a6632004-08-20 23:09:47 +00007225 oldcontainer = ctxt->container;
7226 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7227 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007228 if (type == NULL)
7229 return (NULL);
7230 type->node = node;
7231 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007232 /*
7233 * Check for illegal attributes.
7234 */
7235 attr = node->properties;
7236 while (attr != NULL) {
7237 if (attr->ns == NULL) {
7238 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7239 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7240 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7241 xmlSchemaPIllegalAttrErr(ctxt,
7242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7243 NULL, type, attr);
7244 }
7245 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7246 xmlSchemaPIllegalAttrErr(ctxt,
7247 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7248 NULL, type, attr);
7249 }
7250 attr = attr->next;
7251 }
7252 /*
7253 * Extract and validate attributes.
7254 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007255 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007256 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7257 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7258 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007259 /*
7260 * And now for the children...
7261 */
7262 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007263 child = node->children;
7264 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007265 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7266 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007267 }
7268 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007269 (IS_SCHEMA(child, "group")) ||
7270 (IS_SCHEMA(child, "any")) ||
7271 (IS_SCHEMA(child, "choice")) ||
7272 (IS_SCHEMA(child, "sequence"))) {
7273 subtype = NULL;
7274 if (IS_SCHEMA(child, "element")) {
7275 subtype = (xmlSchemaTypePtr)
7276 xmlSchemaParseElement(ctxt, schema, child, 0);
7277 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007278 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007279 } else if (IS_SCHEMA(child, "any")) {
7280 subtype = xmlSchemaParseAny(ctxt, schema, child);
7281 } else if (IS_SCHEMA(child, "choice")) {
7282 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7283 } else if (IS_SCHEMA(child, "sequence")) {
7284 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7285 }
7286 if (subtype != NULL) {
7287 if (last == NULL) {
7288 type->subtypes = subtype;
7289 last = subtype;
7290 } else {
7291 last->next = subtype;
7292 last = subtype;
7293 }
7294 last->next = NULL;
7295 }
7296 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007297 }
7298 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007299 xmlSchemaPContentErr(ctxt,
7300 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7301 NULL, type, node, child, NULL,
7302 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007303 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007304 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007305
7306 return (type);
7307}
7308
7309/**
7310 * xmlSchemaParseRestriction:
7311 * @ctxt: a schema validation context
7312 * @schema: the schema being built
7313 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007314 *
7315 * parse a XML schema Restriction definition
7316 * *WARNING* this interface is highly subject to change
7317 *
7318 * Returns the type definition or NULL in case of error
7319 */
7320static xmlSchemaTypePtr
7321xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007322 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007323{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007324 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007325 xmlNodePtr child = NULL;
7326 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007327 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007328 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007329
7330 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7331 return (NULL);
7332
7333 oldcontainer = ctxt->container;
7334
William M. Brack2f2a6632004-08-20 23:09:47 +00007335 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7336 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 if (type == NULL)
7338 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007339 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007341 /*
7342 * Check for illegal attributes.
7343 */
7344 attr = node->properties;
7345 while (attr != NULL) {
7346 if (attr->ns == NULL) {
7347 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7348 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7349 xmlSchemaPIllegalAttrErr(ctxt,
7350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7351 NULL, type, attr);
7352 }
7353 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7354 xmlSchemaPIllegalAttrErr(ctxt,
7355 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7356 NULL, type, attr);
7357 }
7358 attr = attr->next;
7359 }
7360 /*
7361 * Extract and validate attributes.
7362 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007363 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007364 /*
7365 * Attribute "base".
7366 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007367 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007368 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007369 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7370 /* TODO: Think about the error code. */
7371 xmlSchemaPMissingAttrErr(ctxt,
7372 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7373 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007374 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007375 /*
7376 * And now for the children...
7377 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007378 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007379 child = node->children;
7380 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007381 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7382 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007383 }
7384 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007385 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7386 if (IS_SCHEMA(child, "all")) {
7387 subtype = (xmlSchemaTypePtr)
7388 xmlSchemaParseAll(ctxt, schema, child);
7389 child = child->next;
7390 type->subtypes = subtype;
7391 } else if (IS_SCHEMA(child, "choice")) {
7392 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7393 child = child->next;
7394 type->subtypes = subtype;
7395 } else if (IS_SCHEMA(child, "sequence")) {
7396 subtype = (xmlSchemaTypePtr)
7397 xmlSchemaParseSequence(ctxt, schema, child);
7398 child = child->next;
7399 type->subtypes = subtype;
7400 } else if (IS_SCHEMA(child, "group")) {
7401 subtype = (xmlSchemaTypePtr)
7402 xmlSchemaParseGroup(ctxt, schema, child, 0);
7403 child = child->next;
7404 type->subtypes = subtype;
7405 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007406 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7407 if (IS_SCHEMA(child, "simpleType")) {
7408 if (type->base != NULL) {
7409 /*
7410 * src-restriction-base-or-simpleType
7411 * Either the base [attribute] or the simpleType [child] of the
7412 * <restriction> element must be present, but not both.
7413 */
7414 xmlSchemaPContentErr(ctxt,
7415 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7416 NULL, NULL, type->node, child,
7417 "The attribute 'base' and the <simpleType> child are "
7418 "mutually exclusive", NULL);
7419 } else {
7420 subtype = (xmlSchemaTypePtr)
7421 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7422 type->baseType = subtype;
7423 }
7424 child = child->next;
7425 }
7426 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007427 if (IS_SCHEMA(child, "simpleType")) {
7428 subtype = (xmlSchemaTypePtr)
7429 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007430 type->subtypes = subtype;
7431 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007432 }
7433 }
7434 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7435 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7436 xmlSchemaFacetPtr facet, lastfacet = NULL;
7437
Daniel Veillard01fa6152004-06-29 17:04:39 +00007438 /*
7439 * Add the facets to the parent simpleType/complexType.
7440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007441 /*
7442 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7443 * Simple Type Definition Schema Representation Constraint:
7444 * *Single Facet Value*
7445 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007446 while ((IS_SCHEMA(child, "minInclusive")) ||
7447 (IS_SCHEMA(child, "minExclusive")) ||
7448 (IS_SCHEMA(child, "maxInclusive")) ||
7449 (IS_SCHEMA(child, "maxExclusive")) ||
7450 (IS_SCHEMA(child, "totalDigits")) ||
7451 (IS_SCHEMA(child, "fractionDigits")) ||
7452 (IS_SCHEMA(child, "pattern")) ||
7453 (IS_SCHEMA(child, "enumeration")) ||
7454 (IS_SCHEMA(child, "whiteSpace")) ||
7455 (IS_SCHEMA(child, "length")) ||
7456 (IS_SCHEMA(child, "maxLength")) ||
7457 (IS_SCHEMA(child, "minLength"))) {
7458 facet = xmlSchemaParseFacet(ctxt, schema, child);
7459 if (facet != NULL) {
7460 if (lastfacet == NULL)
7461 ctxt->ctxtType->facets = facet;
7462 else
7463 lastfacet->next = facet;
7464 lastfacet = facet;
7465 lastfacet->next = NULL;
7466 }
7467 child = child->next;
7468 }
7469 /*
7470 * Create links for derivation and validation.
7471 */
7472 if (lastfacet != NULL) {
7473 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7474
7475 facet = ctxt->ctxtType->facets;
7476 do {
7477 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7478 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007479 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007480 xmlFree(facetLink);
7481 return (NULL);
7482 }
7483 facetLink->facet = facet;
7484 facetLink->next = NULL;
7485 if (lastFacetLink == NULL)
7486 ctxt->ctxtType->facetSet = facetLink;
7487 else
7488 lastFacetLink->next = facetLink;
7489 lastFacetLink = facetLink;
7490 facet = facet->next;
7491 } while (facet != NULL);
7492 }
7493 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007494 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7495 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7496 if (IS_SCHEMA(child, "anyAttribute")) {
7497 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7498 child = child->next;
7499 }
7500 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007501 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007502 /* TODO: Think about the error code. */
7503 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7504 xmlSchemaPContentErr(ctxt,
7505 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7506 NULL, type, node, child, NULL,
7507 "annotation?, (group | all | choice | sequence)?, "
7508 "((attribute | attributeGroup)*, anyAttribute?))");
7509 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7510 xmlSchemaPContentErr(ctxt,
7511 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7512 NULL, type, node, child, NULL,
7513 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7514 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7515 "length | minLength | maxLength | enumeration | whiteSpace | "
7516 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7517 } else {
7518 /* Simple type */
7519 xmlSchemaPContentErr(ctxt,
7520 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7521 NULL, type, node, child, NULL,
7522 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7523 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7524 "length | minLength | maxLength | enumeration | whiteSpace | "
7525 "pattern)*))");
7526 }
7527 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007528 ctxt->container = oldcontainer;
7529 return (type);
7530}
7531
7532/**
7533 * xmlSchemaParseExtension:
7534 * @ctxt: a schema validation context
7535 * @schema: the schema being built
7536 * @node: a subtree containing XML Schema informations
7537 *
7538 * parse a XML schema Extension definition
7539 * *WARNING* this interface is highly subject to change
7540 *
7541 * Returns the type definition or NULL in case of error
7542 */
7543static xmlSchemaTypePtr
7544xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007545 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007546{
7547 xmlSchemaTypePtr type, subtype;
7548 xmlNodePtr child = NULL;
7549 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007550 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007551
7552 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7553 return (NULL);
7554
7555 oldcontainer = ctxt->container;
7556
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007557 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007558 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007559 if (type == NULL)
7560 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007561 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007562 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007563 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007564 ctxt->container = name;
7565
7566 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7567 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007568 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 "<extension>: The attribute \"base\" is missing.\n",
7570 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 }
7572 child = node->children;
7573 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007574 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7575 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007576 }
7577 subtype = NULL;
7578
7579 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007580 subtype = xmlSchemaParseAll(ctxt, schema, child);
7581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007582 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007583 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7584 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007586 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7587 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007588 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007589 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007590 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007591 }
7592 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007593 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007594 if ((ctxt->ctxtType != NULL) &&
7595 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7596 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7597 if (IS_SCHEMA(child, "anyAttribute")) {
7598 ctxt->ctxtType->attributeWildcard =
7599 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7600 child = child->next;
7601 }
7602 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007603 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007604 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7606 "<extension> has unexpected content.\n", type->name,
7607 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007608 }
7609 ctxt->container = oldcontainer;
7610 return (type);
7611}
7612
7613/**
7614 * xmlSchemaParseSimpleContent:
7615 * @ctxt: a schema validation context
7616 * @schema: the schema being built
7617 * @node: a subtree containing XML Schema informations
7618 *
7619 * parse a XML schema SimpleContent definition
7620 * *WARNING* this interface is highly subject to change
7621 *
7622 * Returns the type definition or NULL in case of error
7623 */
7624static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007625xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7626 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007627{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007628 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007629 xmlNodePtr child = NULL;
7630 xmlChar name[30];
7631
7632 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7633 return (NULL);
7634
William M. Bracke7091952004-05-11 15:09:58 +00007635 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007636 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007637 if (type == NULL)
7638 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007639 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007640 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007641 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007642
7643 child = node->children;
7644 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007645 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7646 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007647 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007648 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007649 ctxt->parentItem = type;
7650 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007651 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007652 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007653 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007655 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007656 subtype = (xmlSchemaTypePtr)
7657 xmlSchemaParseExtension(ctxt, schema, child);
7658 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007659 }
7660 type->subtypes = subtype;
7661 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007662 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7664 "<simpleContent> has unexpected content.\n",
7665 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007666 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007667 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007668 return (type);
7669}
7670
7671/**
7672 * xmlSchemaParseComplexContent:
7673 * @ctxt: a schema validation context
7674 * @schema: the schema being built
7675 * @node: a subtree containing XML Schema informations
7676 *
7677 * parse a XML schema ComplexContent definition
7678 * *WARNING* this interface is highly subject to change
7679 *
7680 * Returns the type definition or NULL in case of error
7681 */
7682static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007683xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7684 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007685{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007686 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007687 xmlNodePtr child = NULL;
7688 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007689 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007690
7691 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7692 return (NULL);
7693
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007694 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007695 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007696 if (type == NULL)
7697 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007698 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007699 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007700 /*
7701 * Check for illegal attributes.
7702 */
7703 attr = node->properties;
7704 while (attr != NULL) {
7705 if (attr->ns == NULL) {
7706 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7707 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7708 {
7709 xmlSchemaPIllegalAttrErr(ctxt,
7710 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7711 NULL, NULL, attr);
7712 }
7713 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7714 xmlSchemaPIllegalAttrErr(ctxt,
7715 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7716 NULL, NULL, attr);
7717 }
7718 attr = attr->next;
7719 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007720 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007721 /*
7722 * Handle attribute 'mixed'.
7723 */
7724 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7725 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7726 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7727 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007728 child = node->children;
7729 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007730 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7731 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007732 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007733 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007734 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007735 subtype = NULL;
7736 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007737 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007738 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007739 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007740 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007741 subtype = (xmlSchemaTypePtr)
7742 xmlSchemaParseExtension(ctxt, schema, child);
7743 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007744 }
7745 type->subtypes = subtype;
7746 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007747 xmlSchemaPContentErr(ctxt,
7748 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7749 NULL, NULL, node, child,
7750 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007751 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007752 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 return (type);
7754}
7755
7756/**
7757 * xmlSchemaParseComplexType:
7758 * @ctxt: a schema validation context
7759 * @schema: the schema being built
7760 * @node: a subtree containing XML Schema informations
7761 *
7762 * parse a XML schema Complex Type definition
7763 * *WARNING* this interface is highly subject to change
7764 *
7765 * Returns the type definition or NULL in case of error
7766 */
7767static xmlSchemaTypePtr
7768xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007769 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007770{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007771 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007772 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007773 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007774 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007775 xmlAttrPtr attr;
7776 const xmlChar *attrValue;
7777 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007778 char buf[40];
7779
Daniel Veillard4255d502002-04-16 15:50:10 +00007780
7781 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7782 return (NULL);
7783
Daniel Veillard01fa6152004-06-29 17:04:39 +00007784 ctxtType = ctxt->ctxtType;
7785
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007786 if (topLevel) {
7787 attr = xmlSchemaGetPropNode(node, "name");
7788 if (attr == NULL) {
7789 xmlSchemaPMissingAttrErr(ctxt,
7790 XML_SCHEMAP_S4S_ATTR_MISSING,
7791 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7792 "name", NULL);
7793 return (NULL);
7794 } else if (xmlSchemaPValAttrNode(ctxt,
7795 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7796 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7797 return (NULL);
7798 }
7799 }
7800
7801 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007802 /*
7803 * Parse as local complex type definition.
7804 */
7805 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7806 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7807 if (type == NULL)
7808 return (NULL);
7809 name = (const xmlChar *) buf;
7810 type->node = node;
7811 type->type = XML_SCHEMA_TYPE_COMPLEX;
7812 /*
7813 * TODO: We need the target namespace.
7814 */
7815 } else {
7816 /*
7817 * Parse as global complex type definition.
7818 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007819 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007820 if (type == NULL)
7821 return (NULL);
7822 type->node = node;
7823 type->type = XML_SCHEMA_TYPE_COMPLEX;
7824 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7825 /*
7826 * Set defaults.
7827 */
7828 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7829 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7830 }
7831 /*
7832 * Handle attributes.
7833 */
7834 attr = node->properties;
7835 while (attr != NULL) {
7836 if (attr->ns == NULL) {
7837 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7838 /*
7839 * Attribute "id".
7840 */
7841 type->id = xmlSchemaGetProp(ctxt, node, "id");
7842 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7843 /*
7844 * Attribute "mixed".
7845 */
7846 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7847 (xmlNodePtr) attr))
7848 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7849 } else if (topLevel) {
7850 /*
7851 * Attributes of global complex type definitions.
7852 */
7853 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7854 /* Pass. */
7855 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7856 /*
7857 * Attribute "abstract".
7858 */
7859 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7860 (xmlNodePtr) attr))
7861 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7862 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7863 /*
7864 * Attribute "final".
7865 */
7866 attrValue = xmlSchemaGetNodeContent(ctxt,
7867 (xmlNodePtr) attr);
7868 if (xmlSchemaPValAttrBlockFinal(attrValue,
7869 &(type->flags),
7870 -1,
7871 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7872 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7873 -1, -1, -1) != 0)
7874 {
7875 xmlSchemaPSimpleTypeErr(ctxt,
7876 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7877 &des, type, (xmlNodePtr) attr,
7878 NULL,
7879 "(#all | List of (extension | restriction))",
7880 attrValue, NULL, NULL, NULL);
7881 }
7882 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7883 /*
7884 * Attribute "block".
7885 */
7886 attrValue = xmlSchemaGetNodeContent(ctxt,
7887 (xmlNodePtr) attr);
7888 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7889 -1,
7890 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7891 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7892 -1, -1, -1) != 0) {
7893 xmlSchemaPSimpleTypeErr(ctxt,
7894 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7895 &des, type, (xmlNodePtr) attr,
7896 NULL,
7897 "(#all | List of (extension | restriction)) ",
7898 attrValue, NULL, NULL, NULL);
7899 }
7900 } else {
7901 xmlSchemaPIllegalAttrErr(ctxt,
7902 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7903 &des, type, attr);
7904 }
7905 } else {
7906 xmlSchemaPIllegalAttrErr(ctxt,
7907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7908 &des, type, attr);
7909 }
7910 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7911 xmlSchemaPIllegalAttrErr(ctxt,
7912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7913 &des, type, attr);
7914 }
7915 attr = attr->next;
7916 }
7917 /*
7918 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007919 * This will be only changed if a complex type
7920 * inherits an attribute wildcard from a base type.
7921 */
7922 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007923 /*
7924 * And now for the children...
7925 */
7926 oldcontainer = ctxt->container;
7927 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007928 child = node->children;
7929 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007930 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7931 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007932 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007933 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007934 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007935 /*
7936 * 3.4.3 : 2.2
7937 * Specifying mixed='true' when the <simpleContent>
7938 * alternative is chosen has no effect
7939 */
William M. Bracke7091952004-05-11 15:09:58 +00007940 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7941 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
7943 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007944 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007945 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
7946 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007947 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007948 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007949 /*
7950 * Parse model groups.
7951 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007952 if (IS_SCHEMA(child, "all")) {
7953 subtype = xmlSchemaParseAll(ctxt, schema, child);
7954 child = child->next;
7955 } else if (IS_SCHEMA(child, "choice")) {
7956 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7957 child = child->next;
7958 } else if (IS_SCHEMA(child, "sequence")) {
7959 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7960 child = child->next;
7961 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007962 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007963 child = child->next;
7964 }
7965 if (subtype != NULL)
7966 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007967 /*
7968 * Parse attribute decls/refs.
7969 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007970 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007971 /*
7972 * Parse attribute wildcard.
7973 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007974 if (IS_SCHEMA(child, "anyAttribute")) {
7975 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7976 child = child->next;
7977 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007978 }
7979 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007980 xmlSchemaPContentErr(ctxt,
7981 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7982 &des, type, node, child,
7983 NULL, "(annotation?, (simpleContent | complexContent | "
7984 "((group | all | choice | sequence)?, ((attribute | "
7985 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007986 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007987 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00007988 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007989 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007990 return (type);
7991}
7992
Daniel Veillard4255d502002-04-16 15:50:10 +00007993/**
7994 * xmlSchemaParseSchema:
7995 * @ctxt: a schema validation context
7996 * @node: a subtree containing XML Schema informations
7997 *
7998 * parse a XML schema definition from a node set
7999 * *WARNING* this interface is highly subject to change
8000 *
8001 * Returns the internal XML Schema structure built from the resource or
8002 * NULL in case of error
8003 */
8004static xmlSchemaPtr
8005xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8006{
8007 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008008 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008009 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008010 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008011
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008012 /*
8013 * This one is called by xmlSchemaParse only and is used if
8014 * the schema to be parsed was specified via the API; i.e. not
8015 * automatically by the validated instance document.
8016 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008017 if ((ctxt == NULL) || (node == NULL))
8018 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008019 nberrors = ctxt->nberrors;
8020 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008021 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008022 xmlSchemaImportPtr import;
8023
Daniel Veillard4255d502002-04-16 15:50:10 +00008024 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008025 if (schema == NULL)
8026 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008027 /*
8028 * Disable build of list of items.
8029 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008030 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8031 if (attr != NULL) {
8032 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8033 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8034 /*
8035 * TODO: Should we proceed with an invalid target namespace?
8036 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008037 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8038 } else {
8039 schema->targetNamespace = NULL;
8040 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008041 /*
8042 * Add the current ns name and location to the import table;
8043 * this is needed to have a consistent mechanism, regardless
8044 * if all schemata are constructed dynamically fired by the
8045 * instance or if the schema to be used was specified via
8046 * the API.
8047 */
8048 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8049 schema->targetNamespace);
8050 if (import == NULL) {
8051 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8052 NULL, NULL, (xmlNodePtr) ctxt->doc,
8053 "Internal error: xmlSchemaParseSchema, "
8054 "failed to add an import entry", NULL);
8055 xmlSchemaFree(schema);
8056 schema = NULL;
8057 return (NULL);
8058 }
8059 import->schemaLocation = ctxt->URL;
8060 /*
8061 * NOTE: We won't set the doc here, otherwise it will be freed
8062 * if the import struct is freed.
8063 * import->doc = ctxt->doc;
8064 */
8065
Daniel Veillardc0826a72004-08-10 14:17:33 +00008066 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008067 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008068 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8069 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8070
William M. Brack2f2a6632004-08-20 23:09:47 +00008071 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008072 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8073 } else {
8074 xmlDocPtr doc;
8075
8076 doc = node->doc;
8077
8078 if ((doc != NULL) && (doc->URL != NULL)) {
8079 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8080 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008082 } else {
8083 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8084 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008086 }
8087 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008088 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008089 if (ctxt->nberrors != 0) {
8090 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008091 xmlSchemaFree(schema);
8092 schema = NULL;
8093 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008094 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008095 if (schema != NULL)
8096 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008097 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008098#ifdef DEBUG
8099 if (schema == NULL)
8100 xmlGenericError(xmlGenericErrorContext,
8101 "xmlSchemaParse() failed\n");
8102#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008103 return (schema);
8104}
8105
8106/************************************************************************
8107 * *
8108 * Validating using Schemas *
8109 * *
8110 ************************************************************************/
8111
8112/************************************************************************
8113 * *
8114 * Reading/Writing Schemas *
8115 * *
8116 ************************************************************************/
8117
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008118#if 0 /* Will be enabled if it is clear what options are needed. */
8119/**
8120 * xmlSchemaParserCtxtSetOptions:
8121 * @ctxt: a schema parser context
8122 * @options: a combination of xmlSchemaParserOption
8123 *
8124 * Sets the options to be used during the parse.
8125 *
8126 * Returns 0 in case of success, -1 in case of an
8127 * API error.
8128 */
8129static int
8130xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8131 int options)
8132
8133{
8134 int i;
8135
8136 if (ctxt == NULL)
8137 return (-1);
8138 /*
8139 * WARNING: Change the start value if adding to the
8140 * xmlSchemaParseOption.
8141 */
8142 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8143 if (options & 1<<i) {
8144 return (-1);
8145 }
8146 }
8147 ctxt->options = options;
8148 return (0);
8149}
8150
8151/**
8152 * xmlSchemaValidCtxtGetOptions:
8153 * @ctxt: a schema parser context
8154 *
8155 * Returns the option combination of the parser context.
8156 */
8157static int
8158xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8159
8160{
8161 if (ctxt == NULL)
8162 return (-1);
8163 else
8164 return (ctxt->options);
8165}
8166
8167 void *curItems; /* used for dynamic addition of schemata */
8168 int nbCurItems; /* used for dynamic addition of schemata */
8169 int sizeCurItems; /* used for dynamic addition of schemata */
8170
8171#endif
8172
Daniel Veillard4255d502002-04-16 15:50:10 +00008173/**
8174 * xmlSchemaNewParserCtxt:
8175 * @URL: the location of the schema
8176 *
8177 * Create an XML Schemas parse context for that file/resource expected
8178 * to contain an XML Schemas file.
8179 *
8180 * Returns the parser context or NULL in case of error
8181 */
8182xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008183xmlSchemaNewParserCtxt(const char *URL)
8184{
Daniel Veillard4255d502002-04-16 15:50:10 +00008185 xmlSchemaParserCtxtPtr ret;
8186
8187 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008188 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008189
8190 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8191 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008192 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008193 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 return (NULL);
8195 }
8196 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008197 ret->dict = xmlDictCreate();
8198 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008199 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008200 return (ret);
8201}
8202
8203/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008204 * xmlSchemaNewParserCtxtUseDict:
8205 * @URL: the location of the schema
8206 * @dict: the dictionary to be used
8207 *
8208 * Create an XML Schemas parse context for that file/resource expected
8209 * to contain an XML Schemas file.
8210 *
8211 * Returns the parser context or NULL in case of error
8212 */
8213static xmlSchemaParserCtxtPtr
8214xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8215{
8216 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008217 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008218 if (URL == NULL)
8219 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008220 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008221
8222 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8223 if (ret == NULL) {
8224 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8225 NULL);
8226 return (NULL);
8227 }
8228 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8229 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008230 xmlDictReference(dict);
8231 if (URL != NULL)
8232 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008233 ret->includes = 0;
8234 return (ret);
8235}
8236
8237
8238/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008239 * xmlSchemaNewMemParserCtxt:
8240 * @buffer: a pointer to a char array containing the schemas
8241 * @size: the size of the array
8242 *
8243 * Create an XML Schemas parse context for that memory buffer expected
8244 * to contain an XML Schemas file.
8245 *
8246 * Returns the parser context or NULL in case of error
8247 */
8248xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008249xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8250{
Daniel Veillard6045c902002-10-09 21:13:59 +00008251 xmlSchemaParserCtxtPtr ret;
8252
8253 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008254 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008255
8256 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8257 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008258 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008259 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008260 return (NULL);
8261 }
8262 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8263 ret->buffer = buffer;
8264 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008265 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008266 return (ret);
8267}
8268
8269/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008270 * xmlSchemaNewDocParserCtxt:
8271 * @doc: a preparsed document tree
8272 *
8273 * Create an XML Schemas parse context for that document.
8274 * NB. The document may be modified during the parsing process.
8275 *
8276 * Returns the parser context or NULL in case of error
8277 */
8278xmlSchemaParserCtxtPtr
8279xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8280{
8281 xmlSchemaParserCtxtPtr ret;
8282
8283 if (doc == NULL)
8284 return (NULL);
8285
8286 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8287 if (ret == NULL) {
8288 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8289 NULL);
8290 return (NULL);
8291 }
8292 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8293 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008294 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008295 /* The application has responsibility for the document */
8296 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008297
8298 return (ret);
8299}
8300
8301/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008302 * xmlSchemaFreeParserCtxt:
8303 * @ctxt: the schema parser context
8304 *
8305 * Free the resources associated to the schema parser context
8306 */
8307void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008308xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8309{
Daniel Veillard4255d502002-04-16 15:50:10 +00008310 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008311 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008312 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008313 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008314 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008315 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008316 xmlFree(ctxt->assemble);
8317 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008318 if (ctxt->vctxt != NULL) {
8319 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8320 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008321 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008322 xmlFree(ctxt);
8323}
8324
8325/************************************************************************
8326 * *
8327 * Building the content models *
8328 * *
8329 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008330
Daniel Veillard4255d502002-04-16 15:50:10 +00008331/**
8332 * xmlSchemaBuildAContentModel:
8333 * @type: the schema type definition
8334 * @ctxt: the schema parser context
8335 * @name: the element name whose content is being built
8336 *
8337 * Generate the automata sequence needed for that type
8338 */
8339static void
8340xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008341 xmlSchemaParserCtxtPtr ctxt,
8342 const xmlChar * name)
8343{
Daniel Veillard4255d502002-04-16 15:50:10 +00008344 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008345 xmlGenericError(xmlGenericErrorContext,
8346 "Found unexpected type = NULL in %s content model\n",
8347 name);
8348 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008349 }
8350 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008351 case XML_SCHEMA_TYPE_ANY: {
8352 xmlAutomataStatePtr start, end;
8353 xmlSchemaWildcardPtr wild;
8354 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008355
Daniel Veillardc0826a72004-08-10 14:17:33 +00008356 wild = type->attributeWildcard;
8357
8358 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008359 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008360 "Internal error: xmlSchemaBuildAContentModel, "
8361 "no wildcard on xsd:any.\n", NULL, NULL);
8362 return;
8363 }
8364
8365 start = ctxt->state;
8366 end = xmlAutomataNewState(ctxt->am);
8367
8368 if (type->maxOccurs == 1) {
8369 if (wild->any == 1) {
8370 /*
8371 * We need to add both transitions:
8372 *
8373 * 1. the {"*", "*"} for elements in a namespace.
8374 */
8375 ctxt->state =
8376 xmlAutomataNewTransition2(ctxt->am,
8377 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8378 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8379 /*
8380 * 2. the {"*"} for elements in no namespace.
8381 */
8382 ctxt->state =
8383 xmlAutomataNewTransition2(ctxt->am,
8384 start, NULL, BAD_CAST "*", NULL, type);
8385 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8386
8387 } else if (wild->nsSet != NULL) {
8388 ns = wild->nsSet;
8389 do {
8390 ctxt->state = start;
8391 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8392 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8393 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8394 ns = ns->next;
8395 } while (ns != NULL);
8396
8397 } else if (wild->negNsSet != NULL) {
8398 xmlAutomataStatePtr deadEnd;
8399
8400 deadEnd = xmlAutomataNewState(ctxt->am);
8401 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8402 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8403 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8404 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8405 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8406 }
8407 } else {
8408 int counter;
8409 xmlAutomataStatePtr hop;
8410 int maxOccurs =
8411 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8412 int minOccurs =
8413 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8414
8415 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8416 hop = xmlAutomataNewState(ctxt->am);
8417 if (wild->any == 1) {
8418 ctxt->state =
8419 xmlAutomataNewTransition2(ctxt->am,
8420 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8421 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8422 ctxt->state =
8423 xmlAutomataNewTransition2(ctxt->am,
8424 start, NULL, BAD_CAST "*", NULL, type);
8425 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8426 } else if (wild->nsSet != NULL) {
8427 ns = wild->nsSet;
8428 do {
8429 ctxt->state =
8430 xmlAutomataNewTransition2(ctxt->am,
8431 start, NULL, BAD_CAST "*", ns->value, type);
8432 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8433 ns = ns->next;
8434 } while (ns != NULL);
8435
8436 } else if (wild->negNsSet != NULL) {
8437 xmlAutomataStatePtr deadEnd;
8438
8439 deadEnd = xmlAutomataNewState(ctxt->am);
8440 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8441 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8442 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8443 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8444 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8445 }
8446 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8447 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8448 }
8449 if (type->minOccurs == 0) {
8450 xmlAutomataNewEpsilon(ctxt->am, start, end);
8451 }
8452 ctxt->state = end;
8453 break;
8454 }
8455 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008456 xmlAutomataStatePtr oldstate;
8457 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008458
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008459 /*
8460 * IMPORTANT: This puts element declarations
8461 * (and never element decl. references) into the
8462 * automaton. This is crucial and should not be changed,
8463 * since validating functions rely now on it.
8464 */
8465 particle = (xmlSchemaElementPtr) type;
8466 if (particle->ref != NULL) {
8467 if (particle->refDecl == NULL) {
8468 /*
8469 * Skip content model creation if the reference
8470 * did not resolve to a declaration.
8471 */
8472 break;
8473 } else {
8474 /*
8475 * Referenced global element declaration.
8476 */
8477 elemDecl = particle->refDecl;
8478 }
8479 } else {
8480 /*
8481 * Anonymous element declaration.
8482 */
8483 elemDecl = particle;
8484 }
8485
8486 oldstate = ctxt->state;
8487
8488 if (particle->maxOccurs >= UNBOUNDED) {
8489 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008490 xmlAutomataStatePtr tmp;
8491 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008492
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008493 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008494 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008495 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008496 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008497 particle->minOccurs - 1, UNBOUNDED);
8498 ctxt->state =
8499 xmlAutomataNewTransition2(ctxt->am,
8500 ctxt->state, NULL,
8501 elemDecl->name,
8502 elemDecl->targetNamespace,
8503 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008504 tmp = ctxt->state;
8505 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008506 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008507 ctxt->state =
8508 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008509 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008510
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008511 } else {
8512 ctxt->state =
8513 xmlAutomataNewTransition2(ctxt->am,
8514 ctxt->state, NULL,
8515 elemDecl->name,
8516 elemDecl->targetNamespace,
8517 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8519 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008520 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008521 /* basically an elem* */
8522 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8523 ctxt->state);
8524 }
8525 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008526 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008527 xmlAutomataStatePtr tmp;
8528 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008529
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008530 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8531 oldstate, NULL);
8532 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008533 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008534 particle->minOccurs - 1,
8535 particle->maxOccurs - 1);
8536 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8537 ctxt->state,
8538 NULL,
8539 elemDecl->name,
8540 elemDecl->targetNamespace,
8541 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008542 tmp = ctxt->state;
8543 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008544 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008545 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008546 NULL, counter);
8547 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008548 /* basically an elem? */
8549 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008550 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008551 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008552
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008553 } else {
8554 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8555 ctxt->state,
8556 NULL,
8557 elemDecl->name,
8558 elemDecl->targetNamespace,
8559 (xmlSchemaTypePtr) elemDecl);
8560 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008561 /* basically an elem? */
8562 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008563 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008564 }
8565 }
8566 break;
8567 }
8568 case XML_SCHEMA_TYPE_SEQUENCE:{
8569 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008570
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008571 /*
8572 * If max and min occurances are default (1) then
8573 * simply iterate over the subtypes
8574 */
8575 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8576 subtypes = type->subtypes;
8577 while (subtypes != NULL) {
8578 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8579 subtypes = subtypes->next;
8580 }
8581 } else {
8582 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008583
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008584 if (type->maxOccurs >= UNBOUNDED) {
8585 if (type->minOccurs > 1) {
8586 xmlAutomataStatePtr tmp;
8587 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008588
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008589 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8590 oldstate,
8591 NULL);
8592 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008593
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008594 counter = xmlAutomataNewCounter(ctxt->am,
8595 type->
8596 minOccurs - 1,
8597 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008598
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008599 subtypes = type->subtypes;
8600 while (subtypes != NULL) {
8601 xmlSchemaBuildAContentModel(subtypes, ctxt,
8602 name);
8603 subtypes = subtypes->next;
8604 }
8605 tmp = ctxt->state;
8606 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8607 oldstate, counter);
8608 ctxt->state =
8609 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8610 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008611
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008612 } else {
8613 subtypes = type->subtypes;
8614 while (subtypes != NULL) {
8615 xmlSchemaBuildAContentModel(subtypes, ctxt,
8616 name);
8617 subtypes = subtypes->next;
8618 }
8619 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8620 oldstate);
8621 if (type->minOccurs == 0) {
8622 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8623 ctxt->state);
8624 }
8625 }
8626 } else if ((type->maxOccurs > 1)
8627 || (type->minOccurs > 1)) {
8628 xmlAutomataStatePtr tmp;
8629 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008630
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008631 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8632 oldstate,
8633 NULL);
8634 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008635
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008636 counter = xmlAutomataNewCounter(ctxt->am,
8637 type->minOccurs -
8638 1,
8639 type->maxOccurs -
8640 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008641
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008642 subtypes = type->subtypes;
8643 while (subtypes != NULL) {
8644 xmlSchemaBuildAContentModel(subtypes, ctxt,
8645 name);
8646 subtypes = subtypes->next;
8647 }
8648 tmp = ctxt->state;
8649 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8650 counter);
8651 ctxt->state =
8652 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8653 counter);
8654 if (type->minOccurs == 0) {
8655 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8656 ctxt->state);
8657 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008658
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008659 } else {
8660 subtypes = type->subtypes;
8661 while (subtypes != NULL) {
8662 xmlSchemaBuildAContentModel(subtypes, ctxt,
8663 name);
8664 subtypes = subtypes->next;
8665 }
8666 if (type->minOccurs == 0) {
8667 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8668 ctxt->state);
8669 }
8670 }
8671 }
8672 break;
8673 }
8674 case XML_SCHEMA_TYPE_CHOICE:{
8675 xmlSchemaTypePtr subtypes;
8676 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008678 start = ctxt->state;
8679 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008680
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008681 /*
8682 * iterate over the subtypes and remerge the end with an
8683 * epsilon transition
8684 */
8685 if (type->maxOccurs == 1) {
8686 subtypes = type->subtypes;
8687 while (subtypes != NULL) {
8688 ctxt->state = start;
8689 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8690 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8691 subtypes = subtypes->next;
8692 }
8693 } else {
8694 int counter;
8695 xmlAutomataStatePtr hop;
8696 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8697 UNBOUNDED : type->maxOccurs - 1;
8698 int minOccurs =
8699 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008700
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008701 /*
8702 * use a counter to keep track of the number of transtions
8703 * which went through the choice.
8704 */
8705 counter =
8706 xmlAutomataNewCounter(ctxt->am, minOccurs,
8707 maxOccurs);
8708 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008709
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008710 subtypes = type->subtypes;
8711 while (subtypes != NULL) {
8712 ctxt->state = start;
8713 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8714 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8715 subtypes = subtypes->next;
8716 }
8717 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8718 counter);
8719 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8720 counter);
8721 }
8722 if (type->minOccurs == 0) {
8723 xmlAutomataNewEpsilon(ctxt->am, start, end);
8724 }
8725 ctxt->state = end;
8726 break;
8727 }
8728 case XML_SCHEMA_TYPE_ALL:{
8729 xmlAutomataStatePtr start;
8730 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008731
Daniel Veillard3646d642004-06-02 19:19:14 +00008732 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008733 int lax;
8734
8735 subtypes = type->subtypes;
8736 if (subtypes == NULL)
8737 break;
8738 start = ctxt->state;
8739 while (subtypes != NULL) {
8740 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008741 /*
8742 * the following 'if' was needed to fix bug 139897
8743 * not quite sure why it only needs to be done for
8744 * elements with a 'ref', but it seems to work ok.
8745 */
8746 if (subtypes->ref != NULL)
8747 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008748 elem = (xmlSchemaElementPtr) subtypes;
8749 /*
8750 * NOTE: The {max occurs} of all the particles in the
8751 * {particles} of the group must be 0 or 1.
8752 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008753 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008754 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8755 ctxt->state,
8756 elem->name,
8757 elem->targetNamespace,
8758 1, 1, subtypes);
8759 } else if ((elem->minOccurs == 0) &&
8760 (elem->maxOccurs == 1)) {
8761
8762 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8763 ctxt->state,
8764 elem->name,
8765 elem->targetNamespace,
8766 0,
8767 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008768 subtypes);
8769 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008770 /*
8771 * NOTE: if maxOccurs == 0 then no transition will be
8772 * created.
8773 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008774 subtypes = subtypes->next;
8775 }
8776 lax = type->minOccurs == 0;
8777 ctxt->state =
8778 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8779 lax);
8780 break;
8781 }
8782 case XML_SCHEMA_TYPE_RESTRICTION:
8783 if (type->subtypes != NULL)
8784 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8785 break;
8786 case XML_SCHEMA_TYPE_EXTENSION:
8787 if (type->baseType != NULL) {
8788 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008789
8790 /*
8791 * TODO: Circular definitions will be checked at the
8792 * constraint level. So remove this when the complex type
8793 * constraints are implemented.
8794 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008795 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008796 /* TODO: Change the error code. */
8797 xmlSchemaPCustomErr(ctxt,
8798 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8799 NULL, type, type->node,
8800 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008801 return;
8802 }
8803 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008804 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008805 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008806 subtypes = type->subtypes;
8807 while (subtypes != NULL) {
8808 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8809 subtypes = subtypes->next;
8810 }
8811 } else if (type->subtypes != NULL)
8812 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8813 break;
8814 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008815 /*
8816 * Handle model group definition references.
8817 * NOTE: type->subtypes is the referenced model grop definition;
8818 * and type->subtypes->subtypes is the model group (i.e. <all> or
8819 * <choice> or <sequence>).
8820 */
8821 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8822 (type->subtypes->subtypes != NULL)) {
8823 xmlSchemaTypePtr modelGr;
8824 xmlAutomataStatePtr start, end;
8825
8826 modelGr = type->subtypes->subtypes;
8827 start = ctxt->state;
8828 end = xmlAutomataNewState(ctxt->am);
8829 if (type->maxOccurs == 1) {
8830 ctxt->state = start;
8831 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8832 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8833 } else {
8834 int counter;
8835 xmlAutomataStatePtr hop;
8836 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8837 UNBOUNDED : type->maxOccurs - 1;
8838 int minOccurs =
8839 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8840
8841 counter =
8842 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8843 hop = xmlAutomataNewState(ctxt->am);
8844 ctxt->state = start;
8845 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8846 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8847 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8848 counter);
8849 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8850 counter);
8851 }
8852 if (type->minOccurs == 0) {
8853 xmlAutomataNewEpsilon(ctxt->am, start, end);
8854 }
8855 ctxt->state = end;
8856 break;
8857 }
8858 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008859 case XML_SCHEMA_TYPE_COMPLEX:
8860 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8861 if (type->subtypes != NULL)
8862 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8863 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008864 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8865 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008866 default:
8867 xmlGenericError(xmlGenericErrorContext,
8868 "Found unexpected type %d in %s content model\n",
8869 type->type, name);
8870 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008871 }
8872}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008873
Daniel Veillard4255d502002-04-16 15:50:10 +00008874/**
8875 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008876 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008877 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008878 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008879 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008881 */
8882static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008883xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008884 xmlSchemaParserCtxtPtr ctxt,
8885 const xmlChar * name)
8886{
Daniel Veillard4255d502002-04-16 15:50:10 +00008887 xmlAutomataStatePtr start;
8888
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008889 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8890 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8891 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8892 (type->contModel != NULL))
8893 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008894
8895#ifdef DEBUG_CONTENT
8896 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008897 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008898#endif
8899
Daniel Veillard4255d502002-04-16 15:50:10 +00008900 ctxt->am = xmlNewAutomata();
8901 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008902 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008903 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008904 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 }
8906 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008907 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008908 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008909 type->contModel = xmlAutomataCompile(ctxt->am);
8910 if (type->contModel == NULL) {
8911 xmlSchemaPCustomErr(ctxt,
8912 XML_SCHEMAP_INTERNAL,
8913 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008914 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008915 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008916 xmlSchemaPCustomErr(ctxt,
8917 XML_SCHEMAP_NOT_DETERMINISTIC,
8918 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008920 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008921 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008922#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008923 xmlGenericError(xmlGenericErrorContext,
8924 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008925 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008926#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008927 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008928 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008929 xmlFreeAutomata(ctxt->am);
8930 ctxt->am = NULL;
8931}
8932
8933/**
8934 * xmlSchemaRefFixupCallback:
8935 * @elem: the schema element context
8936 * @ctxt: the schema parser context
8937 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008938 * Resolves the references of an element declaration
8939 * or particle, which has an element declaration as it's
8940 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008941 */
8942static void
8943xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008944 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008945 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008946 const xmlChar * context ATTRIBUTE_UNUSED,
8947 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00008948{
Daniel Veillardc0826a72004-08-10 14:17:33 +00008949 if ((ctxt == NULL) || (elem == NULL) ||
8950 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008951 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008952 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00008953 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008954 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00008955
Daniel Veillardc0826a72004-08-10 14:17:33 +00008956 /*
8957 * TODO: Evaluate, what errors could occur if the declaration is not
8958 * found. It might be possible that the "typefixup" might crash if
8959 * no ref declaration was found.
8960 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008961 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008962 if (elemDecl == NULL) {
8963 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00008964 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008965 NULL, (xmlSchemaTypePtr) elem, elem->node,
8966 "ref", elem->ref, elem->refNs,
8967 XML_SCHEMA_TYPE_ELEMENT, NULL);
8968 } else
8969 elem->refDecl = elemDecl;
8970 } else {
8971 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
8972 xmlSchemaTypePtr type;
8973
8974 /* (type definition) ... otherwise the type definition ·resolved·
8975 * to by the ·actual value· of the type [attribute] ...
8976 */
8977 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
8978 elem->namedTypeNs);
8979 if (type == NULL) {
8980 xmlSchemaPResCompAttrErr(ctxt,
8981 XML_SCHEMAP_SRC_RESOLVE,
8982 NULL, (xmlSchemaTypePtr) elem, elem->node,
8983 "type", elem->namedType, elem->namedTypeNs,
8984 XML_SCHEMA_TYPE_BASIC, "type definition");
8985 } else
8986 elem->subtypes = type;
8987 }
8988 if (elem->substGroup != NULL) {
8989 xmlSchemaElementPtr substHead;
8990
8991 /*
8992 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
8993 * substitutionGroup?
8994 */
8995 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008996 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008997 if (substHead == NULL) {
8998 xmlSchemaPResCompAttrErr(ctxt,
8999 XML_SCHEMAP_SRC_RESOLVE,
9000 NULL, (xmlSchemaTypePtr) elem, NULL,
9001 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9002 XML_SCHEMA_TYPE_ELEMENT, NULL);
9003 } else {
9004 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9005 /*
9006 * (type definition)...otherwise the {type definition} of the
9007 * element declaration ·resolved· to by the ·actual value· of
9008 * the substitutionGroup [attribute], if present
9009 */
9010 if (elem->subtypes == NULL)
9011 elem->subtypes = substHead->subtypes;
9012 }
9013 }
9014 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9015 (elem->substGroup == NULL))
9016 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9017 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009018}
9019
William M. Bracke7091952004-05-11 15:09:58 +00009020/**
9021 * xmlSchemaParseListRefFixup:
9022 * @type: the schema type definition
9023 * @ctxt: the schema parser context
9024 *
9025 * Fixup of the itemType reference of the list type.
9026 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009027static void
William M. Bracke7091952004-05-11 15:09:58 +00009028xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009029{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009030
Daniel Veillard01fa6152004-06-29 17:04:39 +00009031 if (((type->base == NULL) &&
9032 (type->subtypes == NULL)) ||
9033 ((type->base != NULL) &&
9034 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009035 /*
9036 * src-list-itemType-or-simpleType
9037 * Either the itemType [attribute] or the <simpleType> [child] of
9038 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009039 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009040 /*
9041 * TODO: Move this to the parse function.
9042 */
9043 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009044 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009045 NULL, type, type->node,
9046 "The attribute 'itemType' and the <simpleType> child "
9047 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009048 } else if (type->base!= NULL) {
9049 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9050 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009051 xmlSchemaPResCompAttrErr(ctxt,
9052 XML_SCHEMAP_SRC_RESOLVE,
9053 NULL, type, type->node,
9054 "itemType", type->base, type->baseNs,
9055 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009056 }
9057 }
9058 if ((type->subtypes != NULL) &&
9059 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9060 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009061}
9062
9063/**
9064 * xmlSchemaParseUnionRefCheck:
9065 * @typeDecl: the schema type definition
9066 * @ctxt: the schema parser context
9067 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009068 * Checks and builds the memberTypes of the union type.
9069 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009070 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009071static int
William M. Bracke7091952004-05-11 15:09:58 +00009072xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009073 xmlSchemaParserCtxtPtr ctxt)
9074{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009075
Daniel Veillard01fa6152004-06-29 17:04:39 +00009076 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9077 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009078
Daniel Veillard01fa6152004-06-29 17:04:39 +00009079 /* 1 If the <union> alternative is chosen, then [Definition:]
9080 * define the explicit members as the type definitions ·resolved·
9081 * to by the items in the ·actual value· of the memberTypes [attribute],
9082 * if any, followed by the type definitions corresponding to the
9083 * <simpleType>s among the [children] of <union>, if any.
9084 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009085
Daniel Veillard01fa6152004-06-29 17:04:39 +00009086 if (type->type != XML_SCHEMA_TYPE_UNION)
9087 return (-1);
9088 if (ctxt->ctxtType == NULL) {
9089 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009090 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009091 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9092 "available", NULL, NULL);
9093 return (-1);
9094 }
9095 /*
9096 * src-union-memberTypes-or-simpleTypes
9097 * Either the memberTypes [attribute] of the <union> element must
9098 * be non-empty or there must be at least one simpleType [child].
9099 */
9100 if ((type->base == NULL) &&
9101 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009102 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009103 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009104 NULL, NULL, type->node,
9105 "Either the attribute 'memberTypes' must be non-empty "
9106 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009107 }
9108
9109 ctxtType = ctxt->ctxtType;
9110 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009111 xmlAttrPtr attr;
9112 const xmlChar *cur, *end;
9113 xmlChar *tmp;
9114 const xmlChar *localName, *uri;
9115
9116 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009117 cur = type->base;
9118 do {
9119 while (IS_BLANK_CH(*cur))
9120 cur++;
9121 end = cur;
9122 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9123 end++;
9124 if (end == cur)
9125 break;
9126 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009127 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9128 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9129 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009130 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009131 xmlSchemaPResCompAttrErr(ctxt,
9132 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9133 NULL, NULL, type->node, "memberTypes", localName, uri,
9134 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009135 } else {
9136 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9137 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9138 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9139 if (link == NULL) {
9140 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9141 return (-1);
9142 }
9143 link->type = memberType;
9144 link->next = NULL;
9145 if (lastLink == NULL)
9146 ctxtType->memberTypes = link;
9147 else
9148 lastLink->next = link;
9149 lastLink = link;
9150 }
9151 xmlFree(tmp);
9152 cur = end;
9153 } while (*cur != 0);
9154 }
9155 /*
9156 * Add local simple types,
9157 */
9158 memberType = type->subtypes;
9159 while (memberType != NULL) {
9160 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9161 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9162 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9163 if (link == NULL) {
9164 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9165 return (-1);
9166 }
9167 link->type = memberType;
9168 link->next = NULL;
9169 if (lastLink == NULL)
9170 ctxtType->memberTypes = link;
9171 else
9172 lastLink->next = link;
9173 lastLink = link;
9174 memberType = memberType->next;
9175 }
9176 /*
9177 * The actual value is then formed by replacing any union type
9178 * definition in the ·explicit members· with the members of their
9179 * {member type definitions}, in order.
9180 */
9181 link = ctxtType->memberTypes;
9182 while (link != NULL) {
9183 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9184 subLink = link->type->memberTypes;
9185 if (subLink != NULL) {
9186 link->type = subLink->type;
9187 if (subLink->next != NULL) {
9188 lastLink = link->next;
9189 subLink = subLink->next;
9190 prevLink = link;
9191 while (subLink != NULL) {
9192 newLink = (xmlSchemaTypeLinkPtr)
9193 xmlMalloc(sizeof(xmlSchemaTypeLink));
9194 if (newLink == NULL) {
9195 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9196 NULL);
9197 return (-1);
9198 }
9199 newLink->type = memberType;
9200 prevLink->next = newLink;
9201 prevLink = newLink;
9202 newLink->next = lastLink;
9203
9204 subLink = subLink->next;
9205 }
9206 }
9207 }
9208 }
9209 link = link->next;
9210 }
9211
9212 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009213}
9214
Daniel Veillard4255d502002-04-16 15:50:10 +00009215/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009216 * xmlSchemaIsDerivedFromBuiltInType:
9217 * @ctxt: the schema parser context
9218 * @type: the type definition
9219 * @valType: the value type
9220 *
9221 *
9222 * Returns 1 if the type has the given value type, or
9223 * is derived from such a type.
9224 */
William M. Brack803812b2004-06-03 02:11:24 +00009225static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009226xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9227 xmlSchemaTypePtr type, int valType)
9228{
9229 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009230 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009231 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009232 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009233 return(1);
9234 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9235 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9236 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9237 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9238 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9239 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9240 if (type->baseType != NULL)
9241 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9242 valType));
9243 } else if ((type->subtypes != NULL) &&
9244 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9245 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9246 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9247 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9248 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9249 valType));
9250 }
9251
9252 return (0);
9253}
9254
9255/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009256 * xmlSchemaIsDerivedFromBuiltInType:
9257 * @type: the simpleType definition
9258 *
9259 * Returns the primitive type of the given type or
9260 * NULL in case of error.
9261 */
9262static xmlSchemaTypePtr
9263xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9264{
9265 while (type != NULL) {
9266 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9267 return (type);
9268 type = type->baseType;
9269 }
9270
9271 return (NULL);
9272}
9273
9274
9275/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009276 * xmlSchemaBuildAttributeUsesOwned:
9277 * @ctxt: the schema parser context
9278 * @type: the complex type definition
9279 * @cur: the attribute declaration list
9280 * @lastUse: the top of the attribute use list
9281 *
9282 * Builds the attribute uses list on the given complex type.
9283 * This one is supposed to be called by
9284 * xmlSchemaBuildAttributeValidation only.
9285 */
9286static int
9287xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9288 xmlSchemaAttributePtr cur,
9289 xmlSchemaAttributeLinkPtr *uses,
9290 xmlSchemaAttributeLinkPtr *lastUse)
9291{
9292 xmlSchemaAttributeLinkPtr tmp;
9293 while (cur != NULL) {
9294 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9295 /*
9296 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9297 * to by the ·actual value·s of the ref [attribute] of the
9298 * <attributeGroup> [children], if any."
9299 */
9300 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9301 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9302 lastUse) == -1) {
9303 return (-1);
9304 }
9305 } else {
9306 /* W3C: "1 The set of attribute uses corresponding to the
9307 * <attribute> [children], if any."
9308 */
9309 tmp = (xmlSchemaAttributeLinkPtr)
9310 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9311 if (tmp == NULL) {
9312 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9313 return (-1);
9314 }
9315 tmp->attr = cur;
9316 tmp->next = NULL;
9317 if (*uses == NULL)
9318 *uses = tmp;
9319 else
9320 (*lastUse)->next = tmp;
9321 *lastUse = tmp;
9322 }
9323 cur = cur->next;
9324 }
9325 return (0);
9326}
9327
Daniel Veillard50355f02004-06-08 17:52:16 +00009328/**
9329 * xmlSchemaCloneWildcardNsConstraints:
9330 * @ctxt: the schema parser context
9331 * @dest: the destination wildcard
9332 * @source: the source wildcard
9333 *
9334 * Clones the namespace constraints of source
9335 * and assignes them to dest.
9336 * Returns -1 on internal error, 0 otherwise.
9337 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009338static int
9339xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9340 xmlSchemaWildcardPtr *dest,
9341 xmlSchemaWildcardPtr source)
9342{
9343 xmlSchemaWildcardNsPtr cur, tmp, last;
9344
9345 if ((source == NULL) || (*dest == NULL))
9346 return(-1);
9347 (*dest)->any = source->any;
9348 cur = source->nsSet;
9349 last = NULL;
9350 while (cur != NULL) {
9351 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9352 if (tmp == NULL)
9353 return(-1);
9354 tmp->value = cur->value;
9355 if (last == NULL)
9356 (*dest)->nsSet = tmp;
9357 else
9358 last->next = tmp;
9359 last = tmp;
9360 cur = cur->next;
9361 }
9362 if ((*dest)->negNsSet != NULL)
9363 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9364 if (source->negNsSet != NULL) {
9365 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9366 if ((*dest)->negNsSet == NULL)
9367 return(-1);
9368 (*dest)->negNsSet->value = source->negNsSet->value;
9369 } else
9370 (*dest)->negNsSet = NULL;
9371 return(0);
9372}
9373
Daniel Veillard50355f02004-06-08 17:52:16 +00009374/**
9375 * xmlSchemaUnionWildcards:
9376 * @ctxt: the schema parser context
9377 * @completeWild: the first wildcard
9378 * @curWild: the second wildcard
9379 *
9380 * Unions the namespace constraints of the given wildcards.
9381 * @completeWild will hold the resulting union.
9382 * Returns a positive error code on failure, -1 in case of an
9383 * internal error, 0 otherwise.
9384 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009385static int
9386xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9387 xmlSchemaWildcardPtr completeWild,
9388 xmlSchemaWildcardPtr curWild)
9389{
9390 xmlSchemaWildcardNsPtr cur, curB, tmp;
9391
9392 /*
9393 * 1 If O1 and O2 are the same value, then that value must be the
9394 * value.
9395 */
9396 if ((completeWild->any == curWild->any) &&
9397 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9398 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9399
9400 if ((completeWild->negNsSet == NULL) ||
9401 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9402
9403 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009404 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009405
9406 /*
9407 * Check equality of sets.
9408 */
9409 cur = completeWild->nsSet;
9410 while (cur != NULL) {
9411 found = 0;
9412 curB = curWild->nsSet;
9413 while (curB != NULL) {
9414 if (cur->value == curB->value) {
9415 found = 1;
9416 break;
9417 }
9418 curB = curB->next;
9419 }
9420 if (!found)
9421 break;
9422 cur = cur->next;
9423 }
9424 if (found)
9425 return(0);
9426 } else
9427 return(0);
9428 }
9429 }
9430 /*
9431 * 2 If either O1 or O2 is any, then any must be the value
9432 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009433 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009434 if (completeWild->any == 0) {
9435 completeWild->any = 1;
9436 if (completeWild->nsSet != NULL) {
9437 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9438 completeWild->nsSet = NULL;
9439 }
9440 if (completeWild->negNsSet != NULL) {
9441 xmlFree(completeWild->negNsSet);
9442 completeWild->negNsSet = NULL;
9443 }
9444 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009445 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009446 }
9447 /*
9448 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9449 * then the union of those sets must be the value.
9450 */
9451 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9452 int found;
9453 xmlSchemaWildcardNsPtr start;
9454
9455 cur = curWild->nsSet;
9456 start = completeWild->nsSet;
9457 while (cur != NULL) {
9458 found = 0;
9459 curB = start;
9460 while (curB != NULL) {
9461 if (cur->value == curB->value) {
9462 found = 1;
9463 break;
9464 }
9465 curB = curB->next;
9466 }
9467 if (!found) {
9468 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9469 if (tmp == NULL)
9470 return (-1);
9471 tmp->value = cur->value;
9472 tmp->next = completeWild->nsSet;
9473 completeWild->nsSet = tmp;
9474 }
9475 cur = cur->next;
9476 }
9477
9478 return(0);
9479 }
9480 /*
9481 * 4 If the two are negations of different values (namespace names
9482 * or ·absent·), then a pair of not and ·absent· must be the value.
9483 */
9484 if ((completeWild->negNsSet != NULL) &&
9485 (curWild->negNsSet != NULL) &&
9486 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9487 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009488
9489 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009490 }
9491 /*
9492 * 5.
9493 */
9494 if (((completeWild->negNsSet != NULL) &&
9495 (completeWild->negNsSet->value != NULL) &&
9496 (curWild->nsSet != NULL)) ||
9497 ((curWild->negNsSet != NULL) &&
9498 (curWild->negNsSet->value != NULL) &&
9499 (completeWild->nsSet != NULL))) {
9500
9501 int nsFound, absentFound = 0;
9502
9503 if (completeWild->nsSet != NULL) {
9504 cur = completeWild->nsSet;
9505 curB = curWild->negNsSet;
9506 } else {
9507 cur = curWild->nsSet;
9508 curB = completeWild->negNsSet;
9509 }
9510 nsFound = 0;
9511 while (cur != NULL) {
9512 if (cur->value == NULL)
9513 absentFound = 1;
9514 else if (cur->value == curB->value)
9515 nsFound = 1;
9516 if (nsFound && absentFound)
9517 break;
9518 cur = cur->next;
9519 }
9520
9521 if (nsFound && absentFound) {
9522 /*
9523 * 5.1 If the set S includes both the negated namespace
9524 * name and ·absent·, then any must be the value.
9525 */
9526 completeWild->any = 1;
9527 if (completeWild->nsSet != NULL) {
9528 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9529 completeWild->nsSet = NULL;
9530 }
9531 if (completeWild->negNsSet != NULL) {
9532 xmlFree(completeWild->negNsSet);
9533 completeWild->negNsSet = NULL;
9534 }
9535 } else if (nsFound && (!absentFound)) {
9536 /*
9537 * 5.2 If the set S includes the negated namespace name
9538 * but not ·absent·, then a pair of not and ·absent· must
9539 * be the value.
9540 */
9541 if (completeWild->nsSet != NULL) {
9542 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9543 completeWild->nsSet = NULL;
9544 }
9545 if (completeWild->negNsSet == NULL) {
9546 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9547 if (completeWild->negNsSet == NULL)
9548 return (-1);
9549 }
9550 completeWild->negNsSet->value = NULL;
9551 } else if ((!nsFound) && absentFound) {
9552 /*
9553 * 5.3 If the set S includes ·absent· but not the negated
9554 * namespace name, then the union is not expressible.
9555 */
9556 xmlSchemaPErr(ctxt, completeWild->node,
9557 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009558 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009559 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009560 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009561 } else if ((!nsFound) && (!absentFound)) {
9562 /*
9563 * 5.4 If the set S does not include either the negated namespace
9564 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9565 * and a namespace name must be the value.
9566 */
9567 if (completeWild->negNsSet == NULL) {
9568 if (completeWild->nsSet != NULL) {
9569 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9570 completeWild->nsSet = NULL;
9571 }
9572 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9573 if (completeWild->negNsSet == NULL)
9574 return (-1);
9575 completeWild->negNsSet->value = curWild->negNsSet->value;
9576 }
9577 }
9578 return (0);
9579 }
9580 /*
9581 * 6.
9582 */
9583 if (((completeWild->negNsSet != NULL) &&
9584 (completeWild->negNsSet->value == NULL) &&
9585 (curWild->nsSet != NULL)) ||
9586 ((curWild->negNsSet != NULL) &&
9587 (curWild->negNsSet->value == NULL) &&
9588 (completeWild->nsSet != NULL))) {
9589
9590 if (completeWild->nsSet != NULL) {
9591 cur = completeWild->nsSet;
9592 } else {
9593 cur = curWild->nsSet;
9594 }
9595 while (cur != NULL) {
9596 if (cur->value == NULL) {
9597 /*
9598 * 6.1 If the set S includes ·absent·, then any must be the
9599 * value.
9600 */
9601 completeWild->any = 1;
9602 if (completeWild->nsSet != NULL) {
9603 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9604 completeWild->nsSet = NULL;
9605 }
9606 if (completeWild->negNsSet != NULL) {
9607 xmlFree(completeWild->negNsSet);
9608 completeWild->negNsSet = NULL;
9609 }
9610 return (0);
9611 }
9612 cur = cur->next;
9613 }
9614 if (completeWild->negNsSet == NULL) {
9615 /*
9616 * 6.2 If the set S does not include ·absent·, then a pair of not
9617 * and ·absent· must be the value.
9618 */
9619 if (completeWild->nsSet != NULL) {
9620 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9621 completeWild->nsSet = NULL;
9622 }
9623 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9624 if (completeWild->negNsSet == NULL)
9625 return (-1);
9626 completeWild->negNsSet->value = NULL;
9627 }
9628 return (0);
9629 }
9630 return (0);
9631
9632}
9633
Daniel Veillard50355f02004-06-08 17:52:16 +00009634/**
9635 * xmlSchemaIntersectWildcards:
9636 * @ctxt: the schema parser context
9637 * @completeWild: the first wildcard
9638 * @curWild: the second wildcard
9639 *
9640 * Intersects the namespace constraints of the given wildcards.
9641 * @completeWild will hold the resulting intersection.
9642 * Returns a positive error code on failure, -1 in case of an
9643 * internal error, 0 otherwise.
9644 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009645static int
9646xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9647 xmlSchemaWildcardPtr completeWild,
9648 xmlSchemaWildcardPtr curWild)
9649{
William M. Brack803812b2004-06-03 02:11:24 +00009650 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009651
9652 /*
9653 * 1 If O1 and O2 are the same value, then that value must be the
9654 * value.
9655 */
9656 if ((completeWild->any == curWild->any) &&
9657 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9658 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9659
9660 if ((completeWild->negNsSet == NULL) ||
9661 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9662
9663 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009664 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009665
9666 /*
9667 * Check equality of sets.
9668 */
9669 cur = completeWild->nsSet;
9670 while (cur != NULL) {
9671 found = 0;
9672 curB = curWild->nsSet;
9673 while (curB != NULL) {
9674 if (cur->value == curB->value) {
9675 found = 1;
9676 break;
9677 }
9678 curB = curB->next;
9679 }
9680 if (!found)
9681 break;
9682 cur = cur->next;
9683 }
9684 if (found)
9685 return(0);
9686 } else
9687 return(0);
9688 }
9689 }
9690 /*
9691 * 2 If either O1 or O2 is any, then the other must be the value.
9692 */
9693 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9694 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9695 return(-1);
9696 return(0);
9697 }
9698 /*
9699 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9700 * name or ·absent·) and the other is a set of (namespace names or
9701 * ·absent·), then that set, minus the negated value if it was in
9702 * the set, minus ·absent· if it was in the set, must be the value.
9703 */
9704 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9705 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9706 const xmlChar *neg;
9707
9708 if (completeWild->nsSet == NULL) {
9709 neg = completeWild->negNsSet->value;
9710 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9711 return(-1);
9712 } else
9713 neg = curWild->negNsSet->value;
9714 /*
9715 * Remove absent and negated.
9716 */
9717 prev = NULL;
9718 cur = completeWild->nsSet;
9719 while (cur != NULL) {
9720 if (cur->value == NULL) {
9721 if (prev == NULL)
9722 completeWild->nsSet = cur->next;
9723 else
9724 prev->next = cur->next;
9725 xmlFree(cur);
9726 break;
9727 }
9728 prev = cur;
9729 cur = cur->next;
9730 }
9731 if (neg != NULL) {
9732 prev = NULL;
9733 cur = completeWild->nsSet;
9734 while (cur != NULL) {
9735 if (cur->value == neg) {
9736 if (prev == NULL)
9737 completeWild->nsSet = cur->next;
9738 else
9739 prev->next = cur->next;
9740 xmlFree(cur);
9741 break;
9742 }
9743 prev = cur;
9744 cur = cur->next;
9745 }
9746 }
9747
9748 return(0);
9749 }
9750 /*
9751 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9752 * then the intersection of those sets must be the value.
9753 */
9754 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9755 int found;
9756
9757 cur = completeWild->nsSet;
9758 prev = NULL;
9759 while (cur != NULL) {
9760 found = 0;
9761 curB = curWild->nsSet;
9762 while (curB != NULL) {
9763 if (cur->value == curB->value) {
9764 found = 1;
9765 break;
9766 }
9767 curB = curB->next;
9768 }
9769 if (!found) {
9770 if (prev == NULL)
9771 completeWild->nsSet = cur->next;
9772 else
9773 prev->next = cur->next;
9774 tmp = cur->next;
9775 xmlFree(cur);
9776 cur = tmp;
9777 continue;
9778 }
9779 prev = cur;
9780 cur = cur->next;
9781 }
9782
9783 return(0);
9784 }
9785 /* 5 If the two are negations of different namespace names,
9786 * then the intersection is not expressible
9787 */
9788 if ((completeWild->negNsSet != NULL) &&
9789 (curWild->negNsSet != NULL) &&
9790 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9791 (completeWild->negNsSet->value != NULL) &&
9792 (curWild->negNsSet->value != NULL)) {
9793
9794 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009795 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009796 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009797 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009798 }
9799 /*
9800 * 6 If the one is a negation of a namespace name and the other
9801 * is a negation of ·absent·, then the one which is the negation
9802 * of a namespace name must be the value.
9803 */
9804 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9805 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9806 (completeWild->negNsSet->value == NULL)) {
9807 completeWild->negNsSet->value = curWild->negNsSet->value;
9808 }
9809 return(0);
9810}
9811
Daniel Veillard50355f02004-06-08 17:52:16 +00009812/**
9813 * xmlSchemaIsWildcardNsConstraintSubset:
9814 * @ctxt: the schema parser context
9815 * @wildA: the first wildcard
9816 * @wildB: the second wildcard
9817 *
9818 * Returns 1 if the namespace constraint of @wildA is an intensional
9819 * subset of @wildB, 0 otherwise.
9820 */
9821static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009822xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9823 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009824{
Daniel Veillard3646d642004-06-02 19:19:14 +00009825
Daniel Veillard50355f02004-06-08 17:52:16 +00009826 /*
9827 * Schema Component Constraint: Wildcard Subset
9828 */
9829 /*
9830 * 1 super must be any.
9831 */
9832 if (wildB->any)
9833 return (1);
9834 /*
9835 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9836 * 2.2 super must be a pair of not and the same value.
9837 */
9838 if ((wildA->negNsSet != NULL) &&
9839 (wildB->negNsSet != NULL) &&
9840 (wildA->negNsSet->value == wildA->negNsSet->value))
9841 return (1);
9842 /*
9843 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9844 */
9845 if (wildA->nsSet != NULL) {
9846 /*
9847 * 3.2.1 super must be the same set or a superset thereof.
9848 */
9849 if (wildB->nsSet != NULL) {
9850 xmlSchemaWildcardNsPtr cur, curB;
9851 int found = 0;
9852
9853 cur = wildA->nsSet;
9854 while (cur != NULL) {
9855 found = 0;
9856 curB = wildB->nsSet;
9857 while (curB != NULL) {
9858 if (cur->value == curB->value) {
9859 found = 1;
9860 break;
9861 }
9862 curB = curB->next;
9863 }
9864 if (!found)
9865 return (0);
9866 cur = cur->next;
9867 }
9868 if (found)
9869 return (1);
9870 } else if (wildB->negNsSet != NULL) {
9871 xmlSchemaWildcardNsPtr cur;
9872 /*
9873 * 3.2.2 super must be a pair of not and a namespace name or
9874 * ·absent· and that value must not be in sub's set.
9875 */
9876 cur = wildA->nsSet;
9877 while (cur != NULL) {
9878 if (cur->value == wildB->negNsSet->value)
9879 return (0);
9880 cur = cur->next;
9881 }
9882 return (1);
9883 }
9884 }
9885 return (0);
9886}
9887
9888/**
9889 * xmlSchemaBuildCompleteAttributeWildcard:
9890 * @ctxt: the schema parser context
9891 * @attrs: the attribute list
9892 * @completeWild: the resulting complete wildcard
9893 *
9894 * Returns -1 in case of an internal error, 0 otherwise.
9895 */
9896static int
9897xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9898 xmlSchemaAttributePtr attrs,
9899 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009900{
9901 while (attrs != NULL) {
9902 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9903 xmlSchemaAttributeGroupPtr group;
9904
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009905 group = (xmlSchemaAttributeGroupPtr) attrs;
9906 /*
9907 * Handle attribute group references.
9908 */
9909 if (group->ref != NULL) {
9910 if (group->refItem == NULL) {
9911 /*
9912 * TODO: Should we raise a warning here?
9913 */
9914 /*
9915 * The referenced attribute group definition could not
9916 * be resolved beforehand, so skip.
9917 */
9918 attrs = attrs->next;
9919 continue;
9920 } else
9921 group = group->refItem;
9922 }
9923 /*
9924 * For every attribute group definition, an intersected wildcard
9925 * will be created (assumed that a wildcard exists on the
9926 * particular attr. gr. def. or on any contained attr. gr. def
9927 * at all).
9928 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9929 * that the intersection will be performed only once.
9930 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009931 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9932 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009933 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9934 group->attributes, &group->attributeWildcard) == -1)
9935 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009936 }
9937 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9938 }
9939 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009940 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009941 /*
9942 * Copy the first encountered wildcard as context, except for the annotation.
9943 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009944 *completeWild = xmlSchemaAddWildcard(ctxt);
9945 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
9946 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
9947 completeWild, group->attributeWildcard) == -1)
9948 return (-1);
9949 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +00009950 /*
9951 * Although the complete wildcard might not correspond to any
9952 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009953 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +00009954 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009955 (*completeWild)->node = group->attributeWildcard->node;
9956
9957 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
9958 xmlSchemaFreeWildcard(*completeWild);
9959 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009960 }
9961 }
9962 }
9963 attrs = attrs->next;
9964 }
9965
Daniel Veillard50355f02004-06-08 17:52:16 +00009966 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009967}
9968
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009969static int
9970xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
9971 int *fixed,
9972 const xmlChar **value,
9973 xmlSchemaValPtr *val)
9974{
9975 *fixed = 0;
9976 *value = NULL;
9977 if (val != 0)
9978 *val = NULL;
9979
9980 if (item->defValue == NULL)
9981 item = item->refDecl;
9982
9983 if (item == NULL)
9984 return (0);
9985
9986 if (item->defValue != NULL) {
9987 *value = item->defValue;
9988 if (val != 0)
9989 *val = item->defVal;
9990 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
9991 *fixed = 1;
9992 return (1);
9993 }
9994 return (0);
9995}
Daniel Veillard3646d642004-06-02 19:19:14 +00009996/**
9997 * xmlSchemaMatchesWildcardNs:
9998 * @wild: the wildcard
9999 * @ns: the namespace
10000 *
10001 *
10002 * Returns 1 if the given namespace matches the wildcard,
10003 * 0 otherwise.
10004 */
10005static int
10006xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10007{
10008 if (wild == NULL)
10009 return(0);
10010
10011 if (wild->any)
10012 return(1);
10013 else if (wild->nsSet != NULL) {
10014 xmlSchemaWildcardNsPtr cur;
10015
10016 cur = wild->nsSet;
10017 while (cur != NULL) {
10018 if (xmlStrEqual(cur->value, ns))
10019 return(1);
10020 cur = cur->next;
10021 }
10022 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10023 (!xmlStrEqual(wild->negNsSet->value, ns)))
10024 return(1);
10025
10026 return(0);
10027}
10028
10029/**
10030 * xmlSchemaBuildAttributeValidation:
10031 * @ctxt: the schema parser context
10032 * @type: the complex type definition
10033 *
10034 *
10035 * Builds the wildcard and the attribute uses on the given complex type.
10036 * Returns -1 if an internal error occurs, 0 otherwise.
10037 */
10038static int
10039xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10040{
10041 xmlSchemaTypePtr baseType = NULL;
10042 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010043 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010044 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010046 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010047 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010048 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010049
Daniel Veillard01fa6152004-06-29 17:04:39 +000010050 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010051 /*
10052 * Complex Type Definition with complex content Schema Component.
10053 *
10054 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010055 * TODO: Add checks for absent referenced attribute declarations and
10056 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010057 */
10058 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010059 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010060 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010061 "attribute uses already builded.\n",
10062 NULL, NULL);
10063 return (-1);
10064 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010065 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010066 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010067 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010068 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010069 type->name, NULL);
10070 return (-1);
10071 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010072 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010073 if (baseType == anyType)
10074 baseIsAnyType = 1;
10075 /*
10076 * Inherit the attribute uses of the base type.
10077 */
10078 /*
10079 * NOTE: It is allowed to "extend" the anyType complex type.
10080 */
10081 if (!baseIsAnyType) {
10082 if (baseType != NULL) {
10083 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10084 tmp = (xmlSchemaAttributeLinkPtr)
10085 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10086 if (tmp == NULL) {
10087 xmlSchemaPErrMemory(ctxt,
10088 "building attribute uses of complexType", NULL);
10089 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010090 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010091 tmp->attr = cur->attr;
10092 tmp->next = NULL;
10093 if (type->attributeUses == NULL) {
10094 type->attributeUses = tmp;
10095 } else
10096 lastBaseUse->next = tmp;
10097 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010098 }
10099 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010100 }
10101 if ((type->subtypes != NULL) &&
10102 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10103 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010104 /*
10105 * type --> (<simpleContent>|<complexContent>)
10106 * --> (<restriction>|<extension>) --> attributes
10107 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010108 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010109 } else {
10110 /* Short hand form of the complexType. */
10111 attrs = type->attributes;
10112 }
10113 /*
10114 * Handle attribute wildcards.
10115 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010116 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10117 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010118 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010119 * NOTE: During the parse time, the wildcard is created on the complexType
10120 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010121 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 if (err == -1) {
10123 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10124 "Internal error: xmlSchemaBuildAttributeValidation: "
10125 "failed to build an intersected attribute wildcard.\n",
10126 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010127 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010128 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010129
10130 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10131 ((baseIsAnyType) ||
10132 ((baseType != NULL) &&
10133 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10134 (baseType->attributeWildcard != NULL)))) {
10135 if (type->attributeWildcard != NULL) {
10136 /*
10137 * Union the complete wildcard with the base wildcard.
10138 */
10139 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10140 baseType->attributeWildcard) == -1)
10141 return (-1);
10142 } else {
10143 /*
10144 * Just inherit the wildcard.
10145 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010146 /*
10147 * NOTE: This is the only case where an attribute
10148 * wildcard is shared.
10149 */
10150 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10151 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010152 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010153 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010154 }
10155
10156 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10157 if (type->attributeWildcard != NULL) {
10158 /*
10159 * Derivation Valid (Restriction, Complex)
10160 * 4.1 The {base type definition} must also have one.
10161 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010162 if (baseType->attributeWildcard == NULL) {
10163 xmlSchemaPCustomErr(ctxt,
10164 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10165 NULL, type, NULL,
10166 "The type has an attribute wildcard, "
10167 "but the base type %s does not have one",
10168 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10169 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010170 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010171 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010172 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10173 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010174 xmlSchemaPCustomErr(ctxt,
10175 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10176 NULL, type, NULL,
10177 "The attribute wildcard is not a valid "
10178 "subset of the wildcard in the base type %s",
10179 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10180 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010181 return (1);
10182 }
10183 /* 4.3 Unless the {base type definition} is the ·ur-type
10184 * definition·, the complex type definition's {attribute
10185 * wildcard}'s {process contents} must be identical to or
10186 * stronger than the {base type definition}'s {attribute
10187 * wildcard}'s {process contents}, where strict is stronger
10188 * than lax is stronger than skip.
10189 */
10190 if ((type->baseType != anyType) &&
10191 (type->attributeWildcard->processContents <
10192 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010193 xmlSchemaPCustomErr(ctxt,
10194 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10195 NULL, type, NULL,
10196 "The 'process contents' of the attribute wildcard is weaker than "
10197 "the one in the base type %s",
10198 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10199 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010200 return (1);
10201 }
10202 }
10203 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10204 /*
10205 * Derivation Valid (Extension)
10206 * At this point the type and the base have both, either
10207 * no wildcard or a wildcard.
10208 */
10209 if ((baseType->attributeWildcard != NULL) &&
10210 (baseType->attributeWildcard != type->attributeWildcard)) {
10211 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010212 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010213 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010214 xmlSchemaPCustomErr(ctxt,
10215 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10216 NULL, type, NULL,
10217 "The attribute wildcard is not a valid "
10218 "superset of the one in the base type %s",
10219 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10220 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010221 return (1);
10222 }
10223 }
10224 }
10225
Daniel Veillard3646d642004-06-02 19:19:14 +000010226 /*
10227 * Gather attribute uses defined by this type.
10228 */
10229 if (attrs != NULL) {
10230 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10231 &uses, &lastUse) == -1) {
10232 return (-1);
10233 }
10234 }
10235 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10236 * "Two distinct attribute declarations in the {attribute uses} must
10237 * not have identical {name}s and {target namespace}s."
10238 *
10239 * For "extension" this is done further down.
10240 */
10241 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10242 cur = uses;
10243 while (cur != NULL) {
10244 tmp = cur->next;
10245 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010246 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10247 xmlSchemaGetAttrName(tmp->attr))) &&
10248 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10249 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10250
10251 xmlSchemaPAttrUseErr(ctxt,
10252 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10253 NULL, type, NULL, cur->attr,
10254 "Duplicate attribute use %s specified",
10255 xmlSchemaFormatNsUriLocal(&str,
10256 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10257 xmlSchemaGetAttrName(tmp->attr))
10258 );
10259 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010260 break;
10261 }
10262 tmp = tmp->next;
10263 }
10264 cur = cur->next;
10265 }
10266 }
10267 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10268 /*
10269 * Derive by restriction.
10270 */
10271 if (baseIsAnyType) {
10272 type->attributeUses = uses;
10273 } else {
10274 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010275 const xmlChar *bEffValue;
10276 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010277
10278 cur = uses;
10279 while (cur != NULL) {
10280 found = 0;
10281 base = type->attributeUses;
10282 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010283 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10284 xmlSchemaGetAttrName(base->attr)) &&
10285 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10286 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010287
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010288 found = 1;
10289
Daniel Veillard3646d642004-06-02 19:19:14 +000010290 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10291 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10292 /*
10293 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010294 */
10295 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010296 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010297 NULL, type, NULL, cur->attr,
10298 "The 'optional' use is inconsistent with a matching "
10299 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010300 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10301 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10302 /*
10303 * derivation-ok-restriction 3
10304 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010305 xmlSchemaPCustomErr(ctxt,
10306 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10307 NULL, type, NULL,
10308 "A matching attribute use for the 'required' "
10309 "attribute use %s of the base type is missing",
10310 xmlSchemaFormatNsUriLocal(&str,
10311 xmlSchemaGetAttrTargetNsURI(base->attr),
10312 xmlSchemaGetAttrName(base->attr)));
10313 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010314 } else {
10315 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010316 * 2.1.3 [Definition:] Let the effective value
10317 * constraint of an attribute use be its {value
10318 * constraint}, if present, otherwise its {attribute
10319 * declaration}'s {value constraint} .
10320 */
10321 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10322 &bEffValue, 0);
10323 /*
10324 * 2.1.3 ... one of the following must be true
10325 *
10326 * 2.1.3.1 B's ·effective value constraint· is
10327 * ·absent· or default.
10328 */
10329 if ((bEffValue != NULL) &&
10330 (effFixed == 1)) {
10331 const xmlChar *rEffValue = NULL;
10332
10333 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10334 &rEffValue, 0);
10335 /*
10336 * 2.1.3.2 R's ·effective value constraint· is
10337 * fixed with the same string as B's.
10338 */
10339 if ((effFixed == 0) ||
10340 (! xmlStrEqual(rEffValue, bEffValue))) {
10341 xmlSchemaPAttrUseErr(ctxt,
10342 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10343 NULL, type, NULL, cur->attr,
10344 "The effective value constraint of the "
10345 "attribute use is inconsistent with "
10346 "its correspondent of the base type",
10347 NULL);
10348 }
10349 }
10350 /*
10351 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10352 */
10353 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010354 * Override the attribute use.
10355 */
10356 base->attr = cur->attr;
10357 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010358
Daniel Veillard3646d642004-06-02 19:19:14 +000010359 break;
10360 }
10361 base = base->next;
10362 }
10363
10364 if (!found) {
10365 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10366 /*
10367 * derivation-ok-restriction 2.2
10368 */
10369 if ((type->attributeWildcard != NULL) &&
10370 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10371 cur->attr->targetNamespace))
10372 found = 1;
10373
10374 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010375 xmlSchemaPAttrUseErr(ctxt,
10376 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10377 NULL, type, NULL, cur->attr,
10378 "Neither a matching attribute use, "
10379 "nor a matching wildcard in the base type does exist",
10380 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010381 } else {
10382 /*
10383 * Add the attribute use.
10384 *
10385 * Note that this may lead to funny derivation error reports, if
10386 * multiple equal attribute uses exist; but this is not
10387 * allowed anyway, and it will be reported beforehand.
10388 */
10389 tmp = cur;
10390 if (prev != NULL)
10391 prev->next = cur->next;
10392 else
10393 uses = cur->next;
10394 cur = cur->next;
10395 if (type->attributeUses == NULL) {
10396 type->attributeUses = tmp;
10397 } else
10398 lastBaseUse->next = tmp;
10399 lastBaseUse = tmp;
10400
10401 continue;
10402 }
10403 }
10404 }
10405 prev = cur;
10406 cur = cur->next;
10407 }
10408 if (uses != NULL)
10409 xmlSchemaFreeAttributeUseList(uses);
10410 }
10411 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10412 /*
10413 * The spec allows only appending, and not other kinds of extensions.
10414 *
10415 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10416 */
10417 if (uses != NULL) {
10418 if (type->attributeUses == NULL) {
10419 type->attributeUses = uses;
10420 } else
10421 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010422 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010423 } else {
10424 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010425 * Derive implicitely from the ur-type.
10426 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010427 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010428 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010429 /*
10430 * 3.4.6 -> Complex Type Definition Properties Correct
10431 */
10432 if (type->attributeUses != NULL) {
10433 cur = type->attributeUses;
10434 prev = NULL;
10435 while (cur != NULL) {
10436 /*
10437 * 4. Two distinct attribute declarations in the {attribute uses} must
10438 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010439 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010440 * Note that this was already done for "restriction" and types derived from
10441 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010442 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010443 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10444 tmp = cur->next;
10445 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010446 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10447 xmlSchemaGetAttrName(tmp->attr))) &&
10448 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10449 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010450
Daniel Veillardc0826a72004-08-10 14:17:33 +000010451 xmlSchemaPAttrUseErr(ctxt,
10452 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10453 NULL, type, NULL, tmp->attr,
10454 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010455 break;
10456 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010457 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010458 }
10459 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010460 /*
10461 * 5. Two distinct attribute declarations in the {attribute uses} must
10462 * not have {type definition}s which are or are derived from ID.
10463 */
10464 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010465 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010466 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010467 xmlSchemaPAttrUseErr(ctxt,
10468 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10469 NULL, type, NULL, cur->attr,
10470 "There must not exist more than one attribute use, "
10471 "declared of type 'ID' or derived from it",
10472 NULL);
10473 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010474 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010475 id = cur;
10476 }
10477 /*
10478 * Remove "prohibited" attribute uses. The reason this is done at this late
10479 * stage is to be able to catch dublicate attribute uses. So we had to keep
10480 * prohibited uses in the list as well.
10481 */
10482 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10483 tmp = cur;
10484 if (prev == NULL)
10485 type->attributeUses = cur->next;
10486 else
10487 prev->next = cur->next;
10488 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010489 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010490 } else {
10491 prev = cur;
10492 cur = cur->next;
10493 }
10494 }
10495 }
10496 /*
10497 * TODO: This check should be removed if we are 100% sure of
10498 * the base type attribute uses already being built.
10499 */
10500 if ((baseType != NULL) && (!baseIsAnyType) &&
10501 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10502 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010503 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010504 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010505 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010506 baseType->name, NULL);
10507 }
10508 return (0);
10509}
10510
10511/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010512 * xmlSchemaTypeFinalContains:
10513 * @schema: the schema
10514 * @type: the type definition
10515 * @final: the final
10516 *
10517 * Evaluates if a type definition contains the given "final".
10518 * This does take "finalDefault" into account as well.
10519 *
10520 * Returns 1 if the type does containt the given "final",
10521 * 0 otherwise.
10522 */
10523static int
10524xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10525{
10526 int tfinal = final, tflags = type->flags;
10527
10528 if (type == NULL)
10529 return (0);
10530 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10531 switch (final) {
10532 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10533 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10534 break;
10535 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10536 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10537 break;
10538 case XML_SCHEMAS_TYPE_FINAL_LIST:
10539 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10540 break;
10541 case XML_SCHEMAS_TYPE_FINAL_UNION:
10542 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10543 break;
10544 }
10545 tflags = schema->flags;
10546 }
10547 if (tflags & tfinal)
10548 return (1);
10549 else
10550 return (0);
10551
10552}
10553
10554/**
10555 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10556 * @type: the Union Simple Type
10557 *
10558 * Returns a list of member types of @type if existing,
10559 * returns NULL otherwise.
10560 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010561static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010562xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10563{
10564 while (type != NULL) {
10565 if (type->memberTypes != NULL)
10566 return (type->memberTypes);
10567 else
10568 type = type->baseType;
10569 }
10570 return (NULL);
10571}
10572
10573/**
10574 * xmlSchemaGetListSimpleTypeItemType:
10575 * @type: the simple type definition
10576 *
10577 * Returns the item type definition of the list simple type.
10578 */
10579static xmlSchemaTypePtr
10580xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10581{
10582 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10583 return (NULL);
10584 /*
10585 * Note: In libxml2, the built-in types do not reflect
10586 * the datatype hierarchy (yet?) - we have to treat them
10587 * in a special way.
10588 */
10589 if (type->type == XML_SCHEMA_TYPE_BASIC)
10590 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10591 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10592 /* 1 If the <list> alternative is chosen, then the type
10593 * definition ·resolved· to by the ·actual value· of the
10594 * itemType [attribute] of <list>, if present, otherwise
10595 * the type definition corresponding to the <simpleType>
10596 * among the [children] of <list>.
10597 */
10598 return (type->subtypes->subtypes);
10599 else {
10600 /* 2 If the <restriction> option is chosen, then the
10601 * {item type definition} of the {base type definition}.
10602 */
10603 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10604 }
10605}
10606
10607/**
10608 * xmlSchemaCheckCOSSTDerivedOK:
10609 * @type: the derived simple type definition
10610 * @baseType: the base type definition
10611 *
10612 * Checks wheter @type can be validly
10613 * derived from @baseType.
10614 *
10615 * Returns 0 on success, an positive error code otherwise.
10616 */
10617static int
10618xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10619 xmlSchemaTypePtr type,
10620 xmlSchemaTypePtr baseType,
10621 int subset)
10622{
10623 /*
10624 * Schema Component Constraint: Type Derivation OK (Simple)
10625 *
10626 *
10627 * 1 They are the same type definition.
10628 * TODO: The identy check might have to be more complex than this.
10629 */
10630 if (type == baseType)
10631 return (0);
10632 /*
10633 * 2.1 restriction is not in the subset, or in the {final}
10634 * of its own {base type definition};
10635 */
10636 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10637 (xmlSchemaTypeFinalContains(schema,
10638 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10639 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10640 }
10641 /* 2.2 */
10642 if (type->baseType == baseType) {
10643 /*
10644 * 2.2.1 D's ·base type definition· is B.
10645 */
10646 return (0);
10647 }
10648 /*
10649 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10650 * and is validly derived from B given the subset, as defined by this
10651 * constraint.
10652 */
10653 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10654 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10655 return (0);
10656 }
10657 /*
10658 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10659 * definition·.
10660 */
10661 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10662 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10663 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10664 return (0);
10665 }
10666 /*
10667 * 2.2.4 B's {variety} is union and D is validly derived from a type
10668 * definition in B's {member type definitions} given the subset, as
10669 * defined by this constraint.
10670 *
10671 * NOTE: This seems not to involve built-in types, since there is no
10672 * built-in Union Simple Type.
10673 */
10674 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10675 xmlSchemaTypeLinkPtr cur;
10676
10677 cur = baseType->memberTypes;
10678 while (cur != NULL) {
10679 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10680 cur->type, subset) == 0)
10681 return (0);
10682 cur = cur->next;
10683 }
10684 }
10685
10686 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10687}
10688
10689
10690/**
10691 * xmlSchemaCheckSTPropsCorrect:
10692 * @ctxt: the schema parser context
10693 * @type: the simple type definition
10694 *
10695 * Checks st-props-correct.
10696 *
10697 * Returns 0 if the properties are correct,
10698 * if not, a positive error code and -1 on internal
10699 * errors.
10700 */
10701static int
10702xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10703 xmlSchemaTypePtr type)
10704{
10705 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10706 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010707 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010708
Daniel Veillardc0826a72004-08-10 14:17:33 +000010709 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010710 /*
10711 * Schema Component Constraint: Simple Type Definition Properties Correct
10712 *
10713 * NOTE: This is somehow redundant, since we actually built a simple type
10714 * to have all the needed information; this acts as an self test.
10715 */
10716 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10717 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10718 /*
10719 * TODO: 1 The values of the properties of a simple type definition must be as
10720 * described in the property tableau in Datatype definition, modulo the
10721 * impact of Missing Sub-components (§5.3).
10722 */
10723 /* Base type: If the datatype has been ·derived· by ·restriction·
10724 * then the Simple Type Definition component from which it is ·derived·,
10725 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10726 */
10727 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010728 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010729 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010730 NULL, type, NULL,
10731 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010732 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10733 }
10734 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10735 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10736 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010737 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010738 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010739 NULL, type, NULL,
10740 "The base type %s is not a simple type",
10741 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10742 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010743 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10744 }
10745 if ((baseType != anySimpleType) &&
10746 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010747 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010748 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010749 NULL, type, NULL,
10750 "A type, derived by list or union, must have"
10751 "the simple ur-type definition as base type, not %s",
10752 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10753 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010754 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10755 }
10756 /*
10757 * Variety: One of {atomic, list, union}.
10758 */
10759 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10760 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10761 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010762 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010763 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010764 NULL, type, NULL,
10765 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010766 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10767 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010768 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010769
10770 /*
10771 * 2 All simple type definitions must be derived ultimately from the ·simple
10772 * ur-type definition (so· circular definitions are disallowed). That is, it
10773 * must be possible to reach a built-in primitive datatype or the ·simple
10774 * ur-type definition· by repeatedly following the {base type definition}.
10775 */
10776 baseType = type->baseType;
10777 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10778 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10779 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10780 if (baseType == anySimpleType)
10781 break;
10782 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010783 xmlSchemaPCustomErr(ctxt,
10784 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10785 NULL, type, NULL,
10786 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010787 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10788 }
10789 baseType = baseType->baseType;
10790 }
10791 /*
10792 * 3 The {final} of the {base type definition} must not contain restriction.
10793 */
10794 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10795 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010796 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010797 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010798 NULL, type, NULL,
10799 "The 'final' of its base type %s must not contain "
10800 "'restriction'",
10801 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10802 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010803 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10804 }
10805 return (0);
10806}
10807
10808/**
10809 * xmlSchemaCheckDerivationValidSimpleRestriction:
10810 * @ctxt: the schema parser context
10811 * @type: the simple type definition
10812 *
10813 * Checks if the given @type (simpleType) is derived
10814 * validly by restriction.
10815 *
10816 * Returns -1 on internal errors, 0 if the type is validly derived,
10817 * a positive error code otherwise.
10818 */
10819static int
10820xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010821 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010822{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010823 xmlChar *str = NULL;
10824
10825 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010826
10827 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10828 xmlSchemaPErr(ctxt, type->node,
10829 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010830 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10831 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010832 type->name, NULL);
10833 return (-1);
10834 }
10835
10836 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10837 xmlSchemaTypePtr primitive;
10838 /*
10839 * 1.1 The {base type definition} must be an atomic simple
10840 * type definition or a built-in primitive datatype.
10841 */
10842 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010843 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010844 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010845 NULL, type, NULL,
10846 "The base type %s is not an atomic simple type",
10847 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10848 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010849 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10850 }
10851 /* 1.2 The {final} of the {base type definition} must not contain
10852 * restriction.
10853 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010854 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010855 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10856 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010857 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010858 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010859 NULL, type, NULL,
10860 "The final of its base type %s must not contain 'restriction'",
10861 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10862 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010863 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10864 }
10865
10866 /*
10867 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10868 * type definition}, as specified in the appropriate subsection of 3.2
10869 * Primitive datatypes.
10870 */
10871 if (type->facets != NULL) {
10872 xmlSchemaFacetPtr facet;
10873 int ok = 1;
10874
10875 primitive = xmlSchemaGetPrimitiveType(type);
10876 if (primitive == NULL) {
10877 xmlSchemaPErr(ctxt, type->node,
10878 XML_ERR_INTERNAL_ERROR,
10879 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010880 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010881 type->name, NULL);
10882 return (-1);
10883 }
10884 facet = type->facets;
10885 do {
10886 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010887 ok = 0;
10888 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010889 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010890 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010891 }
10892 facet = facet->next;
10893 } while (facet != NULL);
10894 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010895 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010896 }
10897 /*
10898 * TODO: 1.3.2 (facet derivation)
10899 */
10900 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10901 xmlSchemaTypePtr itemType = NULL;
10902
10903 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10904 if (itemType == NULL) {
10905 xmlSchemaPErr(ctxt, type->node,
10906 XML_ERR_INTERNAL_ERROR,
10907 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010908 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010909 type->name, NULL);
10910 return (-1);
10911 }
10912 /*
10913 * 2.1 The {item type definition} must have a {variety} of atomic or
10914 * union (in which case all the {member type definitions}
10915 * must be atomic).
10916 */
10917 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10918 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010919 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010920 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010921 NULL, type, NULL,
10922 "The item type %s must have a variety of atomic or union",
10923 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10924 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010925 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10926 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10927 xmlSchemaTypeLinkPtr member;
10928
10929 member = itemType->memberTypes;
10930 while (member != NULL) {
10931 if ((member->type->flags &
10932 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010933 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010934 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010935 NULL, type, NULL,
10936 "The item type is a union type, but the "
10937 "member type %s of this item type is not atomic",
10938 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10939 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010940 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10941 }
10942 member = member->next;
10943 }
10944 }
10945
10946 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
10947 xmlSchemaFacetPtr facet;
10948 /*
10949 * This is the case if we have: <simpleType><list ..
10950 */
10951 /*
10952 * 2.3.1
10953 * 2.3.1.1 The {final} of the {item type definition} must not
10954 * contain list.
10955 */
10956 if (xmlSchemaTypeFinalContains(ctxt->schema,
10957 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010958 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010959 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010960 NULL, type, NULL,
10961 "The final of its item type %s must not contain 'list'",
10962 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10963 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010964 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
10965 }
10966 /*
10967 * 2.3.1.2 The {facets} must only contain the whiteSpace
10968 * facet component.
10969 */
10970 if (type->facets != NULL) {
10971 facet = type->facets;
10972 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010973 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
10974 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010975 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010976 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010977 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
10978 }
10979 facet = facet->next;
10980 } while (facet != NULL);
10981 }
10982 /*
10983 * TODO: Datatypes states:
10984 * A ·list· datatype can be ·derived· from an ·atomic· datatype
10985 * whose ·lexical space· allows space (such as string or anyURI)or
10986 * a ·union· datatype any of whose {member type definitions}'s
10987 * ·lexical space· allows space.
10988 */
10989 } else {
10990 /*
10991 * This is the case if we have: <simpleType><restriction ...
10992 */
10993 /*
10994 * 2.3.2
10995 * 2.3.2.1 The {base type definition} must have a {variety} of list.
10996 */
10997 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010998 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010999 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011000 NULL, type, NULL,
11001 "The base type %s must be a list type",
11002 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11003 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011004 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11005 }
11006 /*
11007 * 2.3.2.2 The {final} of the {base type definition} must not
11008 * contain restriction.
11009 */
11010 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11011 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011012 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011013 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011014 NULL, type, NULL,
11015 "The final of the base type %s must not contain 'restriction'",
11016 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11017 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011018 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11019 }
11020 /*
11021 * 2.3.2.3 The {item type definition} must be validly derived
11022 * from the {base type definition}'s {item type definition} given
11023 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11024 */
11025 {
11026 xmlSchemaTypePtr baseItemType;
11027
11028 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11029 if (baseItemType == NULL) {
11030 xmlSchemaPErr(ctxt, type->node,
11031 XML_ERR_INTERNAL_ERROR,
11032 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011033 "List simple type '%s': Failed to "
11034 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011035 type->name, type->baseType->name);
11036 return (-1);
11037 }
11038 if ((itemType != baseItemType) &&
11039 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11040 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011041 xmlChar *strBIT = NULL, *strBT = NULL;
11042 xmlSchemaPCustomErrExt(ctxt,
11043 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11044 NULL, type, NULL,
11045 "The item type %s is not validly derived from the "
11046 "item type %s of the base type %s",
11047 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11048 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11049 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11050
11051 FREE_AND_NULL(str)
11052 FREE_AND_NULL(strBIT)
11053 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011054 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11055 }
11056 }
11057
11058 if (type->facets != NULL) {
11059 xmlSchemaFacetPtr facet;
11060 int ok = 1;
11061 /*
11062 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11063 * and enumeration facet components are allowed among the {facets}.
11064 */
11065 facet = type->facets;
11066 do {
11067 switch (facet->type) {
11068 case XML_SCHEMA_FACET_LENGTH:
11069 case XML_SCHEMA_FACET_MINLENGTH:
11070 case XML_SCHEMA_FACET_MAXLENGTH:
11071 case XML_SCHEMA_FACET_WHITESPACE:
11072 /*
11073 * TODO: 2.5.1.2 List datatypes
11074 * The value of ·whiteSpace· is fixed to the value collapse.
11075 */
11076 case XML_SCHEMA_FACET_PATTERN:
11077 case XML_SCHEMA_FACET_ENUMERATION:
11078 break;
11079 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011080 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011081 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011082 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011083 /*
11084 * We could return, but it's nicer to report all
11085 * invalid facets.
11086 */
11087 ok = 0;
11088 }
11089 }
11090 facet = facet->next;
11091 } while (facet != NULL);
11092 if (ok == 0)
11093 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11094 /*
11095 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11096 * is a facet of the same kind in the {facets} of the {base type
11097 * definition} (call this BF),then the DF's {value} must be a valid
11098 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11099 */
11100 }
11101
11102
11103 }
11104 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11105 /*
11106 * 3.1 The {member type definitions} must all have {variety} of
11107 * atomic or list.
11108 */
11109 xmlSchemaTypeLinkPtr member;
11110
11111 member = type->memberTypes;
11112 while (member != NULL) {
11113 if (((member->type->flags &
11114 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11115 ((member->type->flags &
11116 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011117 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011118 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011119 NULL, type, NULL,
11120 "The member type %s is neither an atomic, nor a list type",
11121 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11122 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011123 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11124 }
11125 member = member->next;
11126 }
11127 /*
11128 * 3.3.1 If the {base type definition} is the ·simple ur-type
11129 * definition·
11130 */
11131 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11132 /*
11133 * 3.3.1.1 All of the {member type definitions} must have a
11134 * {final} which does not contain union.
11135 */
11136 member = type->memberTypes;
11137 while (member != NULL) {
11138 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11139 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011140 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011141 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011142 NULL, type, NULL,
11143 "The final of member type %s contains 'union'",
11144 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11145 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011146 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11147 }
11148 member = member->next;
11149 }
11150 /*
11151 * 3.3.1.2 The {facets} must be empty.
11152 */
11153 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011154 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011155 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011156 NULL, type, NULL,
11157 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011158 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11159 }
11160 } else {
11161 /*
11162 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11163 */
11164 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011165 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011166 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011167 NULL, type, NULL,
11168 "The base type %s is not a union type",
11169 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11170 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011171 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11172 }
11173 /*
11174 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11175 */
11176 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11177 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011178 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011179 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011180 NULL, type, NULL,
11181 "The final of its base type %s must not contain 'restriction'",
11182 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11183 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011184 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11185 }
11186 /*
11187 * 3.3.2.3 The {member type definitions}, in order, must be validly
11188 * derived from the corresponding type definitions in the {base
11189 * type definition}'s {member type definitions} given the empty set,
11190 * as defined in Type Derivation OK (Simple) (§3.14.6).
11191 */
11192 {
11193 xmlSchemaTypeLinkPtr baseMember;
11194
11195 /*
11196 * OPTIMIZE: if the type is restricting, it has no local defined
11197 * member types and inherits the member types of the base type;
11198 * thus a check for equality can be skipped.
11199 */
11200 /*
11201 * TODO: Even worse: I cannot see a scenario where a restricting
11202 * union simple type can have other member types as the member
11203 * types of it's base type. This check seems not necessary with
11204 * respect to the derivation process in libxml2.
11205 */
11206 if (type->memberTypes != NULL) {
11207 member = type->memberTypes;
11208 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11209 if ((member == NULL) && (baseMember != NULL)) {
11210 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011211 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011212 "Internal error: "
11213 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011214 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011215 "of member types in the base type\n",
11216 type->name, NULL);
11217 }
11218 while (member != NULL) {
11219 if (baseMember == NULL) {
11220 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011221 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011222 "Internal error: "
11223 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011224 "(3.3.2.3), union simple type '%s', unequal number "
11225 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011226 type->name, NULL);
11227 }
11228 if ((member->type != baseMember->type) &&
11229 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11230 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011231 xmlChar *strBMT = NULL, *strBT = NULL;
11232
11233 xmlSchemaPCustomErrExt(ctxt,
11234 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11235 NULL, type, NULL,
11236 "The member type %s is not validly derived from its "
11237 "corresponding member type %s of the base type %s",
11238 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11239 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11240 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11241 FREE_AND_NULL(str)
11242 FREE_AND_NULL(strBMT)
11243 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011244 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11245 }
11246 member = member->next;
11247 baseMember = baseMember->next;
11248 }
11249 }
11250 }
11251 /*
11252 * 3.3.2.4 Only pattern and enumeration facet components are
11253 * allowed among the {facets}.
11254 */
11255 if (type->facets != NULL) {
11256 xmlSchemaFacetPtr facet;
11257 int ok = 1;
11258
11259 facet = type->facets;
11260 do {
11261 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11262 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011263 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11264 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11265 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011266 ok = 0;
11267 }
11268 facet = facet->next;
11269 } while (facet != NULL);
11270 if (ok == 0)
11271 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11272
11273 }
11274 /*
11275 * TODO: 3.3.2.5 (facet derivation)
11276 */
11277 }
11278 }
11279
11280 return (0);
11281}
11282
11283/**
11284 * xmlSchemaCheckSRCSimpleType:
11285 * @ctxt: the schema parser context
11286 * @type: the simple type definition
11287 *
11288 * Checks crc-simple-type constraints.
11289 *
11290 * Returns 0 if the constraints are satisfied,
11291 * if not a positive error code and -1 on internal
11292 * errors.
11293 */
11294static int
11295xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11296 xmlSchemaTypePtr type)
11297{
11298 /*
11299 * NOTE: src-simple-type 2-4 are redundant, since the checks
11300 * were are done for the corresponding <restriction>, <list> and <union>
11301 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11302 * Maby this can be skipped in the future, if we get sure it's not needed.
11303 */
11304 if (type->subtypes == NULL) {
11305 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011306 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011307 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011308 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011309 type->name, NULL);
11310 return (-1);
11311 }
11312 /*
11313 * src-simple-type.1 The corresponding simple type definition, if any,
11314 * must satisfy the conditions set out in Constraints on Simple Type
11315 * Definition Schema Components (§3.14.6).
11316 */
11317 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11318 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11319 /*
11320 * TODO: Removed this, since it got annoying to get an
11321 * extra error report, if anything failed until now.
11322 * Enable this if needed.
11323 */
11324 /*
11325 xmlSchemaPErr(ctxt, type->node,
11326 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011327 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011328 "on simple type definitions.\n",
11329 type->name, NULL);
11330 */
11331 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11332 }
11333
11334 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11335 /*
11336 * src-simple-type.2 If the <restriction> alternative is chosen,
11337 * either it must have a base [attribute] or a <simpleType> among its
11338 * [children], but not both.
11339 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011340 /*
11341 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11342 * NOTE: This was removed, since this will be already handled
11343 * in the parse function for <restriction>.
11344 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011345 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11346 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11347 * an itemType [attribute] or a <simpleType> among its [children],
11348 * but not both.
11349 * NOTE: baseType is set to the local simple type definiton,
11350 * if existent, at parse time. This is a hack and not nice.
11351 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011352 /*
11353 * TODO: Remove this, and add the check to the parse function of <list>.
11354 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011355 if (((type->subtypes->base == NULL) &&
11356 (type->baseType == NULL)) ||
11357 ((type->subtypes->base != NULL) &&
11358 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011359 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011360 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011361 NULL, type, NULL,
11362 "Either the attribute 'itemType' or the <simpleType> child "
11363 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011364 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11365 }
11366
11367
11368 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11369 xmlSchemaTypeLinkPtr member;
11370 xmlSchemaTypePtr ancestor, anySimpleType;
11371
11372 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11373
11374 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11375 * the <union> alternative is chosen, there must not be any entries
11376 * in the memberTypes [attribute] at any depth which resolve to the
11377 * component corresponding to the <simpleType>.
11378 */
11379 member = type->memberTypes;
11380 while (member != NULL) {
11381 ancestor = member->type;
11382 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11383 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11384 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11385 if (ancestor == anySimpleType)
11386 break;
11387 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011388 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011389 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011390 NULL, type, NULL,
11391 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011392 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11393 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11394 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011395 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011396 * type as item type, which in turn has a list ST as member
11397 * type, we will assume this here as well, since this check
11398 * was not yet performed.
11399 */
11400
11401 }
11402 ancestor = ancestor->baseType;
11403 }
11404 member = member->next;
11405 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011406 }
11407
11408 return (0);
11409}
11410
William M. Brack2f2a6632004-08-20 23:09:47 +000011411#if 0 /* Not yet used code for CT schema validation */
11412static int
11413xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11414 const xmlChar * value,
11415 xmlSchemaTypePtr type,
11416 int fireErrors)
11417{
11418 int ret;
11419 /*
11420 * 3.14.4 Simple Type Definition Validation Rules
11421 * Validation Rule: String Valid
11422 */
11423 /*
11424 * 1 It is schema-valid with respect to that definition as defined
11425 * by Datatype Valid in [XML Schemas: Datatypes].
11426 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011427 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11428 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011429 return (ret);
11430 /*
11431 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11432 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11433 * the string must be a ·declared entity name·.
11434 */
11435 /*
11436 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11437 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11438 * then every whitespace-delimited substring of the string must be a ·declared
11439 * entity name·.
11440 */
11441 /*
11442 * 2.3 otherwise no further condition applies.
11443 */
11444
11445 return (0);
11446}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011447#endif
11448
William M. Brack2f2a6632004-08-20 23:09:47 +000011449
11450static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011451xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11452{
11453 if (vctxt->pctxt == NULL) {
11454 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11455 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11456 if (vctxt->pctxt == NULL) {
11457 xmlSchemaVErr(vctxt, NULL,
11458 XML_SCHEMAV_INTERNAL,
11459 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11460 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011461 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011462 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011463 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011464 /* TODO: Pass user data. */
11465 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11466 }
11467 return (0);
11468}
11469
11470static int
11471xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11472{
11473 if (ctxt->vctxt == NULL) {
11474 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11475 if (ctxt->vctxt == NULL) {
11476 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011477 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011478 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11479 "failed to create a temp. validation context.\n",
11480 NULL, NULL);
11481 return (-1);
11482 }
11483 /* TODO: Pass user data. */
11484 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11485 }
11486 return (0);
11487}
11488
11489/**
11490 * xmlSchemaCheckCOSValidDefault:
11491 * @ctxt: the schema parser context
11492 * @type: the simple type definition
11493 * @value: the default value
11494 * @node: an optional node (the holder of the value)
11495 *
11496 * Checks the "cos-valid-default" constraints.
11497 *
11498 * Returns 0 if the constraints are satisfied,
11499 * if not, a positive error code and -1 on internal
11500 * errors.
11501 */
11502static int
11503xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11504 xmlSchemaValidCtxtPtr vctxt,
11505 xmlSchemaTypePtr type,
11506 const xmlChar *value,
11507 xmlNodePtr node)
11508{
11509 int ret = 0;
11510
11511 /*
11512 * cos-valid-default:
11513 * Schema Component Constraint: Element Default Valid (Immediate)
11514 * For a string to be a valid default with respect to a type
11515 * definition the appropriate case among the following must be true:
11516 */
11517 /*
11518 * NOTE: This has to work without a given node (the holder of the
11519 * value), since it should work on the component, i.e. an underlying
11520 * DOM must not be mandatory.
11521 */
11522 if ((pctxt == NULL) || (vctxt == NULL)) {
11523 xmlSchemaPErr(pctxt, node,
11524 XML_SCHEMAP_INTERNAL,
11525 "Internal error: xmlSchemaCheckCOSValidDefault, "
11526 "bad arguments: the parser and/or validation context is "
11527 "missing.\n",
11528 NULL, NULL);
11529 return (-1);
11530 }
11531 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011532 /*
11533 * Complex type.
11534 *
11535 * 2.1 its {content type} must be a simple type definition or mixed.
11536 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011537 /*
11538 * TODO: Adjust this when the content type will be computed
11539 * correctly.
11540 */
11541 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11542 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11543 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11544 xmlSchemaPSimpleTypeErr(pctxt,
11545 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11546 NULL, NULL, node,
11547 type, NULL, NULL,
11548 "If the type of a constraint value is complex, its content "
11549 "type must be mixed or a simple type",
11550 NULL, NULL);
11551 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11552 }
11553 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011554 /*
11555 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11556 * particle must be ·emptiable· as defined by Particle Emptiable
11557 * (§3.9.6).
11558 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011559
William M. Brack2f2a6632004-08-20 23:09:47 +000011560 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011561 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011562 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011563 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011564 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011565 }
11566 /*
11567 * 1 If the type definition is a simple type definition, then the string
11568 * must be ·valid· with respect to that definition as defined by String
11569 * Valid (§3.14.4).
11570 *
11571 * AND
11572 *
11573 * 2.2.1 If the {content type} is a simple type definition, then the
11574 * string must be ·valid· with respect to that simple type definition
11575 * as defined by String Valid (§3.14.4).
11576 */
11577 vctxt->node = node;
11578 vctxt->cur = NULL;
11579 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11580 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11581 if (ret < 0) {
11582 xmlSchemaPErr(pctxt, node,
11583 /* NOTNICE: error code: This function will be used during
11584 * schema construction and xsi:type validation.
11585 */
11586 XML_SCHEMAP_INTERNAL,
11587 "Internal error: xmlSchemaCheckCOSValidDefault, "
11588 "while validating a value constaint value.\n",
11589 NULL, NULL);
11590
11591 }
11592 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011593}
11594
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011595#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011596/**
11597 * xmlSchemaGetSTContentOfCT:
11598 * @ctxt: the schema parser context
11599 * @type: the complex type definition
11600 *
11601 *
11602 * Returns the corresponding simple type for the content of
11603 * the complex type.
11604 */
11605static xmlSchemaTypePtr
11606xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11607 xmlSchemaTypePtr type)
11608{
11609 xmlSchemaTypePtr orig = type, anyType;
11610
11611 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11612 while ((type != NULL) && (type != anyType) &&
11613 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11614 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11615 return(type);
11616 type = type->baseType;
11617 }
11618 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011619 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011620 NULL, orig, NULL,
11621 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11622 "no simple type for the content of complex type '%s' could be "
11623 "computed", orig->name);
11624 return (NULL);
11625}
11626
11627
William M. Brack2f2a6632004-08-20 23:09:47 +000011628
William M. Brack2f2a6632004-08-20 23:09:47 +000011629
11630/**
11631 * xmlSchemaCheckCOSCTExtends:
11632 * @ctxt: the schema parser context
11633 * @type: the complex type definition
11634 *
11635 * Schema Component Constraint: Derivation Valid (Extension)
11636 *
11637 * Returns 0 if the constraints are satisfied, a positive
11638 * error code if not and -1 if an internal error occured.
11639 */
11640static int
11641xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11642 xmlSchemaTypePtr type)
11643{
11644 xmlSchemaTypePtr base;
11645 /*
11646 * 1 If the {base type definition} is a complex type definition,
11647 * then all of the following must be true:
11648 */
11649 base = type->baseType;
11650 if (base == NULL) {
11651 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011652 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011653 NULL, type, NULL,
11654 "Internal error: xmlSchemaCheckCOSCTExtends, "
11655 "the complex type '%s' has no base type", type->name);
11656 return (-1);
11657 }
11658 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11659 /*
11660 * 1.1 The {final} of the {base type definition} must not
11661 * contain extension.
11662 */
11663 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11664 xmlSchemaPCustomErr(ctxt,
11665 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11666 NULL, type, NULL,
11667 "The 'final' of the base type definition "
11668 "contains extension", NULL);
11669 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11670 }
11671 /*
11672 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11673 * of the complex type definition itself, that is, for every attribute
11674 * use in the {attribute uses} of the {base type definition}, there
11675 * must be an attribute use in the {attribute uses} of the complex
11676 * type definition itself whose {attribute declaration} has the same
11677 * {name}, {target namespace} and {type definition} as its attribute
11678 * declaration
11679 *
11680 * NOTE: This will be already satisfied by the way the attribute uses
11681 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11682 * is not needed.
11683 */
11684
11685 /*
11686 * 1.3 If it has an {attribute wildcard}, the complex type definition
11687 * must also have one, and the base type definition's {attribute
11688 * wildcard}'s {namespace constraint} must be a subset of the complex
11689 * type definition's {attribute wildcard}'s {namespace constraint},
11690 * as defined by Wildcard Subset (§3.10.6).
11691 *
11692 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11693 * this check is not needed.
11694 */
11695
11696 /*
11697 * 1.4 One of the following must be true:
11698 *
11699 * 1.4.1 The {content type} of the {base type definition} and the
11700 * {content type} of the complex type definition itself must be the same
11701 * simple type definition
11702 */
11703
11704
11705
11706 } else {
11707 /*
11708 * 2 If the {base type definition} is a simple type definition,
11709 * then all of the following must be true:
11710 */
11711 /*
11712 * 2.1 The {content type} must be the same simple type definition.
11713 */
11714 /*
11715 * 2.2 The {final} of the {base type definition} must not contain
11716 * extension
11717 */
11718 }
11719
11720}
11721
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011722static int
11723xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11724 xmlSchemaTypePtr type)
11725{
11726 xmlSchemaTypePtr base, content;
11727 int OK = 0;
11728
11729 /*
11730 * TODO: Adjust the error codes here, as I used
11731 * XML_SCHEMAP_SRC_CT_1 only yet.
11732 */
11733 /*
11734 * Schema Representation Constraint:
11735 * Complex Type Definition Representation OK
11736 */
11737 base = type->baseType;
11738 if (base == NULL) {
11739 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11740 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11741 type->name);
11742 return (-1);
11743 }
11744
11745 if (type->subtypes != NULL) {
11746 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11747 if IS_COMPLEX_TYPE(base) {
11748 /*
11749 * 1 If the <complexContent> alternative is chosen, the type definition
11750 * ·resolved· to by the ·actual value· of the base [attribute]
11751 * must be a complex type definition;
11752 */
11753 xmlSchemaPCustomErr(ctxt,
11754 XML_SCHEMAP_SRC_CT_1,
11755 NULL, type, NULL,
11756 "The base type is not a complex type", NULL);
11757 return (XML_SCHEMAP_SRC_CT_1);
11758 }
11759 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11760
11761 if IS_SIMPLE_TYPE(base) {
11762 if (type->flags &
11763 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11764 /*
11765 * 2.1.3 only if the <extension> alternative is also
11766 * chosen, a simple type definition.
11767 */
11768 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11769 xmlSchemaPCustomErr(ctxt,
11770 XML_SCHEMAP_SRC_CT_1,
11771 NULL, type, NULL,
11772 "A complex type (simple content) cannot restrict "
11773 "an other simple type",
11774 NULL);
11775 return (XML_SCHEMAP_SRC_CT_1);
11776 }
11777 OK = 1;
11778
11779 } else { /* if IS_SIMPLE_TYPE(base) */
11780 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11781 /*
11782 * 2.1.2 only if the <restriction> alternative is also
11783 * chosen, a complex type definition whose {content type}
11784 * is mixed and a particle emptyable.
11785 */
11786 /*
11787 * FIXME TODO: Check for *empiable particle* is missing.
11788 */
11789 if ((type->flags &
11790 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11791 xmlSchemaPCustomErr(ctxt,
11792 XML_SCHEMAP_SRC_CT_1,
11793 NULL, type, NULL,
11794 "A complex type (simple content) cannot "
11795 "extend an other complex type which has a "
11796 "content type of: 'mixed' and emptiable particle",
11797 NULL);
11798 return (XML_SCHEMAP_SRC_CT_1);
11799 }
11800 /*
11801 * NOTE: This will be fired as well, if the base type
11802 * is *'anyType'*.
11803 * NOTE: type->subtypes->subtypes will be the
11804 * <restriction> item.
11805 */
11806 if (type->subtypes->subtypes == NULL) {
11807 /* Yes, this is paranoid programming. */
11808 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11809 NULL, type, NULL,
11810 "Internal error: xmlSchemaCheckSRCCT, "
11811 "'%s', <simpleContent> has no <restriction>",
11812 type->name);
11813 return (-1);
11814 }
11815 /*
11816 * 2.2 If clause 2.1.2 above is satisfied, then there
11817 * must be a <simpleType> among the [children] of
11818 * <restriction>.
11819 */
11820 if (type->subtypes->subtypes->type !=
11821 XML_SCHEMA_TYPE_SIMPLE) {
11822 /* TODO: Change error code to ..._SRC_CT_2_2. */
11823 xmlSchemaPCustomErr(ctxt,
11824 XML_SCHEMAP_SRC_CT_1,
11825 NULL, type, NULL,
11826 "A <simpleType> is expected among the children "
11827 "of <restriction>", NULL);
11828 return (XML_SCHEMAP_SRC_CT_1);
11829 }
11830 OK = 1;
11831 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11832 /*
11833 * 2.1.1 a complex type definition whose {content type} is a
11834 * simple type definition;
11835 */
11836 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11837 xmlSchemaPCustomErr(ctxt,
11838 XML_SCHEMAP_SRC_CT_1,
11839 NULL, type, NULL,
11840 "A complex type (simple content) cannot "
11841 "be derived from the complex type '%s'",
11842 base->name);
11843 return (XML_SCHEMAP_SRC_CT_1);
11844 }
11845 content = base->contentTypeDef;
11846 if (content == NULL) {
11847 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11848 NULL, type, NULL,
11849 "Internal error: xmlSchemaCheckSRCCT, "
11850 "'%s', base type has no content type",
11851 type->name);
11852 return (-1);
11853 }
11854 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11855 xmlSchemaPCustomErr(ctxt,
11856 XML_SCHEMAP_SRC_CT_1,
11857 NULL, type, NULL,
11858 "A complex type (simple content) cannot "
11859 "be derived from the complex type '%s'",
11860 base->name);
11861 return (XML_SCHEMAP_SRC_CT_1);
11862 }
11863 }
11864 }
11865 }
11866 }
11867 /*
11868 * TODO: 3 The corresponding complex type definition component must
11869 * satisfy the conditions set out in Constraints on Complex Type
11870 * Definition Schema Components (§3.4.6);
11871 *
11872 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11873 * above for {attribute wildcard} is satisfied, the intensional
11874 * intersection must be expressible, as defined in Attribute Wildcard
11875 * Intersection (§3.10.6).
11876 */
11877
11878}
William M. Brack2f2a6632004-08-20 23:09:47 +000011879#endif
11880
Daniel Veillard01fa6152004-06-29 17:04:39 +000011881/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011882 * xmlSchemaGroupDefFixup:
11883 * @typeDecl: the schema model group definition
11884 * @ctxt: the schema parser context
11885 *
11886 * Fixes model group definitions.
11887 */
11888static void
11889xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11890 xmlSchemaParserCtxtPtr ctxt,
11891 const xmlChar * name ATTRIBUTE_UNUSED)
11892{
11893 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11894 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11895 xmlSchemaTypePtr groupDef;
11896 /*
11897 * Resolve the reference.
11898 */
11899 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11900 group->refNs);
11901 if (groupDef == NULL) {
11902 xmlSchemaPResCompAttrErr(ctxt,
11903 XML_SCHEMAP_SRC_RESOLVE,
11904 NULL, group, NULL,
11905 "ref", group->ref, group->refNs,
11906 XML_SCHEMA_TYPE_GROUP, NULL);
11907 return;
11908 }
11909 group->subtypes = groupDef;
11910 }
11911}
11912
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011913#if 0 /* Enable when the content type will be computed. */
11914static int
11915xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11916 xmlSchemaTypePtr type)
11917{
11918 xmlSchemaTypePtr base, res = NULL;
11919
11920 base = type->baseType;
11921 if (base == NULL) {
11922 xmlSchemaPCustomErr(ctxt,
11923 XML_SCHEMAP_INTERNAL,
11924 NULL, type, NULL,
11925 "Internal error: xmlSchemaGetContentType, "
11926 "the complex type '%s' has no base type", type->name);
11927 return (-1);
11928 }
11929 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11930 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11931 xmlSchemaTypePtr start;
11932 /*
11933 * Effective 'mixed'.
11934 */
11935 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11936 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11937 /*
11938 * Effective content.
11939 */
11940 if (IS_ANYTYPE(base))
11941 start = type;
11942 else
11943 start = type->subtypes;
11944
11945 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
11946 xmlSchemaTypePtr baseContentItem;
11947
11948 /*
11949 * Complex type with simple content.
11950 */
11951 if IS_COMPLEX_TYPE(base) {
11952 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11953 /*
11954 * Summary: a complex type (simple content) can *restrict*
11955 * a complex type with the following content type:
11956 * 1. 'mixed' and an emptiable particle
11957 * 2. simple type
11958 */
11959 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
11960 /*
11961 * 2 if the {content type} of the base type is mixed and a
11962 * particle which is ·emptiable·,
11963 * [...]
11964 * then starting from the simple type definition
11965 * corresponding to the <simpleType> among the [children]
11966 * of <restriction> (**which must be present**)
11967 *
11968 * FIXME TODO: Handle "emptiable particle".
11969 */
11970 res = type->subtypes->subtypes;
11971 if (res == NULL) {
11972 xmlSchemaPCustomErr(ctxt,
11973 XML_SCHEMAP_INTERNAL,
11974 NULL, type, NULL,
11975 "Internal error: xmlSchemaGetContentType, "
11976 "CT '%s' (restricting): <simpleContent> has no "
11977 "<restriction>",
11978 type->name);
11979 return (-1);
11980 }
11981
11982 res->subtypes;
11983 if (res == NULL) {
11984 xmlSchemaPCustomErr(ctxt,
11985 XML_SCHEMAP_INTERNAL,
11986 NULL, type, NULL,
11987 "Internal error: xmlSchemaGetContentType, "
11988 "CT '%s' (restricting): <restriction> has no "
11989 "mandatory <simpleType>",
11990 type->name);
11991 return (-1);
11992 }
11993 } else {
11994 baseContentItem = base->contentTypeDef;
11995 if (baseContentItem == NULL) {
11996 xmlSchemaPCustomErr(ctxt,
11997 XML_SCHEMAP_INTERNAL,
11998 NULL, type, NULL,
11999 "Internal error: xmlSchemaGetContentType, "
12000 "CT '%s' (restricting), the base type has no "
12001 "content type", type->name);
12002 return (-1);
12003 }
12004 if IS_SIMPLE_TYPE(baseContentItem) {
12005 /*
12006 * 1 If the base type is a complex type whose own
12007 * {content type} is a simple type and the <restriction>
12008 * alternative is chosen
12009 */
12010 /* type->subtypes->subtypes will be the restriction item.*/
12011 res = type->subtypes->subtypes;
12012 if (res == NULL) {
12013 xmlSchemaPCustomErr(ctxt,
12014 XML_SCHEMAP_INTERNAL,
12015 NULL, type, NULL,
12016 "Internal error: xmlSchemaGetContentType, "
12017 "CT '%s' (restricting): <simpleType> has no "
12018 "<restriction>", type->name);
12019 return (-1);
12020 }
12021 /*
12022 * 1.1 the simple type definition corresponding to the
12023 * <simpleType> among the [children] of <restriction>if
12024 * there is one;
12025 */
12026 res = res->subtypes;
12027 if (res == NULL) {
12028 /*
12029 * 1.2 otherwise the {content type}
12030 * of the base type .
12031 */
12032 res = baseContentItem;
12033 }
12034 }
12035 }
12036 /*
12037 * SPECIAL TODO: If *restricting* the spec wants us to
12038 * create an *additional* simple type which restricts the
12039 * located simple type; we won't do this yet, and look how
12040 * far we get with it.
12041 */
12042 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12043 /*
12044 * Summary: a complex type (simple content) can *extend*
12045 * only a complex base with a simple type as content.
12046 */
12047 /*
12048 * 3 If the type definition ·resolved· to by the ·actual
12049 * value· of the base [attribute] is a complex type
12050 * definition (whose own {content type} *must be* a simple
12051 * type definition, see below) and the *<extension>*
12052 * alternative is chosen, then the {content type} of that
12053 * complex type definition;
12054 */
12055 res = base->contentTypeDef;
12056 if (res == NULL) {
12057 xmlSchemaPCustomErr(ctxt,
12058 XML_SCHEMAP_INTERNAL,
12059 NULL, type, NULL,
12060 "Internal error: xmlSchemaGetContentType, "
12061 "CT '%s' (extending), the base type has no content "
12062 "type", type->name);
12063 return (-1);
12064 }
12065 if (! IS_SIMPLE_TYPE(res)) {
12066 xmlSchemaPCustomErr(ctxt,
12067 XML_SCHEMAP_INTERNAL,
12068 NULL, type, NULL,
12069 "Internal error: xmlSchemaGetContentType, "
12070 "CT '%s' (extending), the content type of the "
12071 "base is not a simple type", type->name);
12072 return (-1);
12073 }
12074 }
12075 } else /* if IS_COMPLEX_TYPE(base) */
12076 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12077 /*
12078 * 4 otherwise (the type definition ·resolved· to by the
12079 * ·actual value· of the base [attribute] is a simple type
12080 * definition and the <extension> alternative is chosen),
12081 * then that simple type definition.
12082 */
12083 res = base;
12084 }
12085 type->contentTypeDef = res;
12086 if (res == NULL) {
12087 xmlSchemaPCustomErr(ctxt,
12088 XML_SCHEMAP_INTERNAL,
12089 NULL, type, NULL,
12090 "Internal error: xmlSchemaGetContentType, "
12091 "'%s', the content type could not be determined",
12092 type->name);
12093 return (-1);
12094 }
12095
12096 }
12097
12098}
12099#endif
12100
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012101/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012102 * xmlSchemaTypeFixup:
12103 * @typeDecl: the schema type definition
12104 * @ctxt: the schema parser context
12105 *
12106 * Fixes the content model of the type.
12107 */
12108static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012109xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012110 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012111{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012112 xmlSchemaTypePtr ctxtType;
12113
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012114 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012115 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012116 /*
12117 * Do not allow the following types to be typefixed, prior to
12118 * the corresponding simple/complex types.
12119 */
12120 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012121 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012122 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12123 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12124 case XML_SCHEMA_TYPE_UNION:
12125 case XML_SCHEMA_TYPE_RESTRICTION:
12126 case XML_SCHEMA_TYPE_EXTENSION:
12127 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012128 default:
12129 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012130 }
12131 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012132 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012133 name = item->name;
12134 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12135 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012136 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012137 if (item->subtypes != NULL) {
12138 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012139 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012140 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012141 NULL);
12142 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012143 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012144 XML_SCHEMA_CONTENT_SIMPLE;
12145 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012146 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012147 break;
12148 }
12149 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012150 xmlSchemaTypePtr base = NULL;
12151
12152 ctxt->ctxtType->flags |=
12153 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012154 if (item->baseType != NULL)
12155 base = item->baseType;
12156 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012157 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012158 xmlSchemaGetType(ctxt->schema, item->base,
12159 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012160 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012161 xmlSchemaPResCompAttrErr(ctxt,
12162 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012163 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012164 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12165 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012166 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012167 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012168 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 xmlSchemaTypeFixup(base, ctxt, NULL);
12170 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012171 }
12172 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012173 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12174 /*
12175 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012176 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012177 /*
12178 * Content type.
12179 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012180 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012181 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012182 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12183 else if ((item->subtypes->subtypes == NULL) &&
12184 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012185 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012186 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012187 XML_SCHEMA_TYPE_SEQUENCE)))
12188 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012189 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12190 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012191 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012192 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012194 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012195 else {
12196 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012197 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012198 XML_SCHEMA_CONTENT_ELEMENTS;
12199 }
12200 } else {
12201 /*
12202 * SimpleType restriction.
12203 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012204 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012205 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012206 break;
12207 }
12208 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012209 xmlSchemaTypePtr base = NULL;
12210 xmlSchemaContentType explicitContentType;
12211
12212 /*
12213 * An extension does exist on a complexType only.
12214 */
12215 ctxt->ctxtType->flags |=
12216 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012217 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012218 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012219 xmlSchemaPCustomErr(ctxt,
12220 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012221 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012222 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012223 return;
12224 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012225 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012226 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012227 xmlSchemaGetType(ctxt->schema, item->base,
12228 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012229 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012230 xmlSchemaPResCompAttrErr(ctxt,
12231 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012232 NULL, item, item->node,
12233 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012234 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012235 } else if (base->contentType ==
12236 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012237 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012238 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012239 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012240 }
12241 /*
12242 * The type definition ·resolved· to by the ·actual
12243 * value· of the base [attribute]
12244 */
12245 ctxt->ctxtType->baseType = base;
12246 /*
12247 * TODO: This one is still needed for computation of
12248 * the content model by xmlSchemaBuildAContentModel.
12249 * Try to get rid of it.
12250 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012251 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012252 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012253 if ((item->subtypes != NULL) &&
12254 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12255 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012256
12257 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012258 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012259 /* 1.1.1 */
12260 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012261 else if ((item->subtypes->subtypes == NULL) &&
12262 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012263 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012264 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012265 XML_SCHEMA_TYPE_SEQUENCE)))
12266 /* 1.1.2 */
12267 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012268 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012269 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012270 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012271 /* 1.1.3 */
12272 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12273 if (base != NULL) {
12274 /* It will be reported later, if the base is missing. */
12275 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12276 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012277 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012278 } else if (base->contentType ==
12279 XML_SCHEMA_CONTENT_EMPTY) {
12280 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012281 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012282 XML_SCHEMA_CONTENT_ELEMENTS;
12283 } else {
12284 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012285 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012286 XML_SCHEMA_CONTENT_ELEMENTS;
12287 }
12288 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012289 break;
12290 }
12291 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012292 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012293 ctxt->ctxtType = item;
12294 /*
12295 * Start with an empty content-type type.
12296 */
12297 if (item->subtypes == NULL)
12298 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12299
12300 if ((item->subtypes == NULL) ||
12301 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012302 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012303 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012304 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12305 /*
12306 * This case is understood as shorthand for complex
12307 * content restricting the ur-type definition, and
12308 * the details of the mappings should be modified as
12309 * necessary.
12310 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012311 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12312 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012313 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012314 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012315 * Assume that we inherit the content-type type
12316 * from 'anyType', which is 'mixed' and a particle
12317 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318 */
12319 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012320 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012321 /*
12322 * Fixup the sub components.
12323 */
12324 if ((item->subtypes != NULL) &&
12325 (item->subtypes->contentType ==
12326 XML_SCHEMA_CONTENT_UNKNOWN)) {
12327 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012328 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012329 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12330 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12331 } else if (item->subtypes != NULL) {
12332 /*
12333 * Use the content-type type of the model groups
12334 * defined, if 'mixed' is not set. If 'mixed' is set
12335 * it will expand the content-type by allowing character
12336 * content to appear.
12337 */
12338 item->contentType =
12339 item->subtypes->contentType;
12340 }
12341 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012342 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012343 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012344 break;
12345 }
12346 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012347 if (item->subtypes == NULL) {
12348 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12349 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12350 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012351 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012352 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012353 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12354 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012355 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012356 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012357 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012358 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012359 if (item->subtypes != NULL)
12360 item->contentType =
12361 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012362 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012363 /*
12364 * Removed due to implementation of the build of attribute uses.
12365 */
12366 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012367 if (item->attributes == NULL)
12368 item->attributes =
12369 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012370 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012371 }
12372 break;
12373 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012374 case XML_SCHEMA_TYPE_SIMPLE:
12375 /*
12376 * Simple Type Definition Schema Component
12377 *
12378 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012379 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012380 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12381 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012382 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012383 ctxt->ctxtType = item;
12384 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012385 }
12386 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012387 if ((item->baseType != NULL) &&
12388 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012389 XML_SCHEMA_CONTENT_UNKNOWN)) {
12390 /* OPTIMIZE: Actually this one will never by hit, since
12391 * the base type is already type-fixed in <restriction>.
12392 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012393 ctxt->ctxtType = item;
12394 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012395 }
12396 /* Base type:
12397 * 2 If the <list> or <union> alternative is chosen,
12398 * then the ·simple ur-type definition·.
12399 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012400 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012401 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012402 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12403 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12404 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012406 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12407 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12408 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012409 XML_SCHEMA_TYPE_RESTRICTION) {
12410 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12411
12412 /*
12413 * Variety
12414 * If the <restriction> alternative is chosen, then the
12415 * {variety} of the {base type definition}.
12416 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012417 if (item->baseType != NULL) {
12418 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012419 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012420 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12421 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012422 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012423 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12424 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012425 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012426 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012427 /*
12428 * Schema Component Constraint: Simple Type Restriction
12429 * (Facets)
12430 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12431 * applied beforehand.
12432 *
12433 * 3 The {facets} of R are the union of S and the {facets}
12434 * of B, eliminating duplicates. To eliminate duplicates,
12435 * when a facet of the same kind occurs in both S and the
12436 * {facets} of B, the one in the {facets} of B is not
12437 * included, with the exception of enumeration and pattern
12438 * facets, for which multiple occurrences with distinct values
12439 * are allowed.
12440 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 if (item->baseType->facetSet != NULL) {
12442 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012443 if (last != NULL)
12444 while (last->next != NULL)
12445 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012446 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012447 for (; cur != NULL; cur = cur->next) {
12448 /*
12449 * Base patterns won't be add here:
12450 * they are ORed in a type and
12451 * ANDed in derived types. This will
12452 * happed at validation level by
12453 * walking the base axis of the type.
12454 */
12455 if (cur->facet->type ==
12456 XML_SCHEMA_FACET_PATTERN)
12457 continue;
12458 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012459 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012460 (cur->facet->type !=
12461 XML_SCHEMA_FACET_PATTERN) &&
12462 (cur->facet->type !=
12463 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012464 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012465 do {
12466 if (cur->facet->type ==
12467 facet->facet->type)
12468 break;
12469 facet = facet->next;
12470 } while (facet != NULL);
12471 }
12472 if (facet == NULL) {
12473 facet = (xmlSchemaFacetLinkPtr)
12474 xmlMalloc(sizeof(xmlSchemaFacetLink));
12475 if (facet == NULL) {
12476 xmlSchemaPErrMemory(ctxt,
12477 "fixing simpleType", NULL);
12478 return;
12479 }
12480 facet->facet = cur->facet;
12481 facet->next = NULL;
12482 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012483 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012484 else
12485 last->next = facet;
12486 last = facet;
12487 }
12488 }
12489 }
12490 }
12491 }
12492 /*
12493 * Check constraints.
12494 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012495 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012496 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012497 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012498 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012499 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012500 case XML_SCHEMA_TYPE_ALL:
12501 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012502 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012503 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012504 case XML_SCHEMA_TYPE_GROUP:
12505 /*
12506 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12507 */
12508 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012509 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012510 xmlSchemaParseListRefFixup(item, ctxt);
12511 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012512 break;
12513 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012514 xmlSchemaParseUnionRefCheck(item, ctxt);
12515 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012516 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012517 case XML_SCHEMA_TYPE_BASIC:
12518 case XML_SCHEMA_TYPE_ANY:
12519 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012520 case XML_SCHEMA_TYPE_UR:
12521 case XML_SCHEMA_TYPE_ELEMENT:
12522 case XML_SCHEMA_TYPE_ATTRIBUTE:
12523 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012524 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012525 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012526 case XML_SCHEMA_FACET_MININCLUSIVE:
12527 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12528 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12529 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12530 case XML_SCHEMA_FACET_TOTALDIGITS:
12531 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12532 case XML_SCHEMA_FACET_PATTERN:
12533 case XML_SCHEMA_FACET_ENUMERATION:
12534 case XML_SCHEMA_FACET_WHITESPACE:
12535 case XML_SCHEMA_FACET_LENGTH:
12536 case XML_SCHEMA_FACET_MAXLENGTH:
12537 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012538 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12539 if (item->subtypes != NULL)
12540 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012541 break;
12542 }
12543 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012544#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012545 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012546 xmlGenericError(xmlGenericErrorContext,
12547 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012548 item->node->doc->URL,
12549 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012550 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012551 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012552 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012553 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012554 case XML_SCHEMA_CONTENT_SIMPLE:
12555 xmlGenericError(xmlGenericErrorContext, "simple\n");
12556 break;
12557 case XML_SCHEMA_CONTENT_ELEMENTS:
12558 xmlGenericError(xmlGenericErrorContext, "elements\n");
12559 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012560 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012561 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12562 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012563 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012564 xmlGenericError(xmlGenericErrorContext, "empty\n");
12565 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012566 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012567 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12568 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 /* Removed, since not used. */
12570 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012571 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012572 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12573 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012575 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012576 xmlGenericError(xmlGenericErrorContext, "basic\n");
12577 break;
12578 default:
12579 xmlGenericError(xmlGenericErrorContext,
12580 "not registered !!!\n");
12581 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012582 }
12583#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012584}
12585
12586/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012587 * xmlSchemaCheckFacet:
12588 * @facet: the facet
12589 * @typeDecl: the schema type definition
12590 * @ctxt: the schema parser context or NULL
12591 * @name: name of the type
12592 *
12593 * Checks the default values types, especially for facets
12594 *
12595 * Returns 0 if okay or -1 in cae of error
12596 */
12597int
12598xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012599 xmlSchemaTypePtr typeDecl,
12600 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012601{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012602 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012603 int ret = 0, reuseValCtxt = 0;
12604
Daniel Veillardce682bc2004-11-05 17:22:25 +000012605 if ((facet == NULL) || (typeDecl == NULL))
12606 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012607 /*
12608 * TODO: will the parser context be given if used from
12609 * the relaxNG module?
12610 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012611
12612 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012613 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012614 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012615 }
12616 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012617 case XML_SCHEMA_FACET_MININCLUSIVE:
12618 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12619 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012620 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12621 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012622 /*
12623 * Okay we need to validate the value
12624 * at that point.
12625 */
12626 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012627 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012628
12629 /* 4.3.5.5 Constraints on enumeration Schema Components
12630 * Schema Component Constraint: enumeration valid restriction
12631 * It is an ·error· if any member of {value} is not in the
12632 * ·value space· of {base type definition}.
12633 *
12634 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12635 * The value ·must· be in the
12636 * ·value space· of the ·base type·.
12637 */
12638 /*
12639 * This function is intended to deliver a compiled value
12640 * on the facet. In XML Schemas the type holding a facet,
12641 * cannot be a built-in type. Thus to ensure that other API
12642 * calls (relaxng) do work, if the given type is a built-in
12643 * type, we will assume that the given built-in type *is
12644 * already* the base type.
12645 */
12646 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12647 base = typeDecl->baseType;
12648 if (base == NULL) {
12649 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012650 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012651 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012652 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012653 typeDecl->name, NULL);
12654 return (-1);
12655 }
12656 } else
12657 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012658 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012659 * This avoids perseverative creation of the
12660 * validation context if a parser context is
12661 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012662 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012663 if (ctxt != NULL) {
12664 reuseValCtxt = 1;
12665 if (ctxt->vctxt == NULL) {
12666 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12667 return (-1);
12668 }
12669 vctxt = ctxt->vctxt;
12670 } else {
12671 vctxt = xmlSchemaNewValidCtxt(NULL);
12672 if (vctxt == NULL) {
12673 xmlSchemaPErr(ctxt, typeDecl->node,
12674 XML_SCHEMAP_INTERNAL,
12675 "Internal error: xmlSchemaCheckFacet, "
12676 "creating a new validation context.\n",
12677 NULL, NULL);
12678 return (-1);
12679 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012680 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012681
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012682 vctxt->node = facet->node;
12683 vctxt->cur = NULL;
12684 /*
12685 * NOTE: This call does not check the content nodes,
12686 * since they are not available:
12687 * facet->node is just the node holding the facet
12688 * definition, *not* the attribute holding the *value*
12689 * of the facet.
12690 */
12691 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12692 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012693 facet->val = vctxt->value;
12694 vctxt->value = NULL;
12695 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012696 /* error code */
12697 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012698 xmlSchemaPErrExt(ctxt, facet->node,
12699 XML_SCHEMAP_INVALID_FACET,
12700 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012701 "Type definition '%s': The value '%s' of the "
12702 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012703 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012704 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012705 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012706 }
12707 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012708 } else if (ret < 0) {
12709 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012710 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012711 NULL, NULL, NULL,
12712 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012713 "failed to validate the value '%s' name of the "
12714 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012715 facet->value,
12716 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12717 base->name, NULL, NULL);
12718 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012719 }
12720 if (reuseValCtxt == 0)
12721 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012722 break;
12723 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012724 case XML_SCHEMA_FACET_PATTERN:
12725 facet->regexp = xmlRegexpCompile(facet->value);
12726 if (facet->regexp == NULL) {
12727 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012728 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 "Type definition '%s': The value '%s' of the "
12730 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012731 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012732 ret = -1;
12733 }
12734 break;
12735 case XML_SCHEMA_FACET_TOTALDIGITS:
12736 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12737 case XML_SCHEMA_FACET_LENGTH:
12738 case XML_SCHEMA_FACET_MAXLENGTH:
12739 case XML_SCHEMA_FACET_MINLENGTH:{
12740 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012741
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012742 tmp =
12743 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12744 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012745 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012746 if (tmp != 0) {
12747 /* error code */
12748 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012749 xmlSchemaPErrExt(ctxt, facet->node,
12750 XML_SCHEMAP_INVALID_FACET_VALUE,
12751 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012752 "Type definition '%s': The value '%s' of the "
12753 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012754 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012755 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012756 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012757 }
12758 ret = -1;
12759 }
12760 break;
12761 }
12762 case XML_SCHEMA_FACET_WHITESPACE:{
12763 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12764 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12765 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12766 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12767 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12768 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12769 } else {
12770 if (ctxt != NULL) {
12771 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012772 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012773 "Type definition '%s': The value '%s' of the "
12774 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012775 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012776 }
12777 ret = -1;
12778 }
12779 }
12780 default:
12781 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012782 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012783 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012784}
12785
12786/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012787 * xmlSchemaCheckDefaults:
12788 * @typeDecl: the schema type definition
12789 * @ctxt: the schema parser context
12790 *
12791 * Checks the default values types, especially for facets
12792 */
12793static void
12794xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012795 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012796{
Daniel Veillard4255d502002-04-16 15:50:10 +000012797 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012798 name = typeDecl->name;
12799 /*
12800 * NOTE: It is intended to use the facets list, instead
12801 * of facetSet.
12802 */
12803 if (typeDecl->facets != NULL) {
12804 xmlSchemaFacetPtr facet = typeDecl->facets;
12805
12806 while (facet != NULL) {
12807 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12808 facet = facet->next;
12809 }
12810 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012811}
12812
12813/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012814 * xmlSchemaGetCircModelGrDefRef:
12815 * @ctxtGr: the searched model group
12816 * @list: the list of model groups to be processed
12817 *
12818 * This one is intended to be used by
12819 * xmlSchemaCheckGroupDefCircular only.
12820 *
12821 * Returns the circular model group definition reference, otherwise NULL.
12822 */
12823static xmlSchemaTypePtr
12824xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12825 xmlSchemaTypePtr gr)
12826{
12827 xmlSchemaTypePtr circ = NULL;
12828 int marked;
12829 /*
12830 * We will search for an model group reference which
12831 * references the context model group definition.
12832 */
12833 while (gr != NULL) {
12834 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12835 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12836 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12837 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12838 (gr->subtypes != NULL)) {
12839 marked = 0;
12840 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12841 (gr->ref != NULL)) {
12842 if (gr->subtypes == ctxtGrDef)
12843 return (gr);
12844 else if (gr->subtypes->flags &
12845 XML_SCHEMAS_TYPE_MARKED) {
12846 gr = gr->next;
12847 continue;
12848 } else {
12849 /*
12850 * Mark to avoid infinite recursion on
12851 * circular references not yet examined.
12852 */
12853 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12854 marked = 1;
12855 }
12856 if (gr->subtypes->subtypes != NULL)
12857 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12858 gr->subtypes->subtypes);
12859 /*
12860 * Unmark the visited model group definition.
12861 */
12862 if (marked)
12863 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12864 if (circ != NULL)
12865 return (circ);
12866 } else {
12867 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12868 (xmlSchemaTypePtr) gr->subtypes);
12869 if (circ != NULL)
12870 return (circ);
12871 }
12872
12873 }
12874 gr = gr->next;
12875 }
12876 return (NULL);
12877}
12878
12879/**
12880 * xmlSchemaCheckGroupDefCircular:
12881 * attrGr: the model group definition
12882 * @ctxt: the parser context
12883 * @name: the name
12884 *
12885 * Checks for circular references to model group definitions.
12886 */
12887static void
12888xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12889 xmlSchemaParserCtxtPtr ctxt,
12890 const xmlChar * name ATTRIBUTE_UNUSED)
12891{
12892 /*
12893 * Schema Component Constraint: Model Group Correct
12894 * 2 Circular groups are disallowed. That is, within the {particles}
12895 * of a group there must not be at any depth a particle whose {term}
12896 * is the group itself.
12897 */
12898 /*
12899 * NOTE: "gr->subtypes" holds the referenced group.
12900 */
12901 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12902 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12903 (modelGrDef->subtypes == NULL))
12904 return;
12905 else {
12906 xmlSchemaTypePtr circ;
12907
12908 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12909 if (circ != NULL) {
12910 /*
12911 * TODO: Report the referenced attr group as QName.
12912 */
12913 xmlSchemaPCustomErr(ctxt,
12914 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12915 NULL, NULL, circ->node,
12916 "Circular reference to the model group definition '%s' "
12917 "defined", modelGrDef->name);
12918 /*
12919 * NOTE: We will cut the reference to avoid further
12920 * confusion of the processor.
12921 * TODO: SPEC: Does the spec define how to process here?
12922 */
12923 circ->subtypes = NULL;
12924 }
12925 }
12926}
12927
12928
12929/**
12930 * xmlSchemaGetCircAttrGrRef:
12931 * @ctxtGr: the searched attribute group
12932 * @attr: the current attribute list to be processed
12933 *
12934 * This one is intended to be used by
12935 * xmlSchemaCheckSRCAttributeGroupCircular only.
12936 *
12937 * Returns the circular attribute grou reference, otherwise NULL.
12938 */
12939static xmlSchemaAttributeGroupPtr
12940xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12941 xmlSchemaAttributePtr attr)
12942{
12943 xmlSchemaAttributeGroupPtr circ = NULL, gr;
12944 int marked;
12945 /*
12946 * We will search for an attribute group reference which
12947 * references the context attribute group.
12948 */
12949 while (attr != NULL) {
12950 marked = 0;
12951 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12952 gr = (xmlSchemaAttributeGroupPtr) attr;
12953 if (gr->refItem != NULL) {
12954 if (gr->refItem == ctxtGr)
12955 return (gr);
12956 else if (gr->refItem->flags &
12957 XML_SCHEMAS_ATTRGROUP_MARKED) {
12958 attr = attr->next;
12959 continue;
12960 } else {
12961 /*
12962 * Mark as visited to avoid infinite recursion on
12963 * circular references not yet examined.
12964 */
12965 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
12966 marked = 1;
12967 }
12968 }
12969 if (gr->attributes != NULL)
12970 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
12971 /*
12972 * Unmark the visited group's attributes.
12973 */
12974 if (marked)
12975 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
12976 if (circ != NULL)
12977 return (circ);
12978 }
12979 attr = attr->next;
12980 }
12981 return (NULL);
12982}
12983
12984/**
12985 * xmlSchemaCheckSRCAttributeGroupCircular:
12986 * attrGr: the attribute group definition
12987 * @ctxt: the parser context
12988 * @name: the name
12989 *
12990 * Checks for circular references of attribute groups.
12991 */
12992static void
12993xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
12994 xmlSchemaParserCtxtPtr ctxt,
12995 const xmlChar * name ATTRIBUTE_UNUSED)
12996{
12997 /*
12998 * Schema Representation Constraint:
12999 * Attribute Group Definition Representation OK
13000 * 3 Circular group reference is disallowed outside <redefine>.
13001 * That is, unless this element information item's parent is
13002 * <redefine>, then among the [children], if any, there must
13003 * not be an <attributeGroup> with ref [attribute] which resolves
13004 * to the component corresponding to this <attributeGroup>. Indirect
13005 * circularity is also ruled out. That is, when QName resolution
13006 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13007 * any <attributeGroup>s with a ref [attribute] among the [children],
13008 * it must not be the case that a ·QName· is encountered at any depth
13009 * which resolves to the component corresponding to this <attributeGroup>.
13010 */
13011 /*
13012 * Only global components can be referenced.
13013 */
13014 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13015 (attrGr->attributes == NULL))
13016 return;
13017 else {
13018 xmlSchemaAttributeGroupPtr circ;
13019
13020 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13021 if (circ != NULL) {
13022 /*
13023 * TODO: Report the referenced attr group as QName.
13024 */
13025 xmlSchemaPCustomErr(ctxt,
13026 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13027 NULL, NULL, circ->node,
13028 "Circular reference to the attribute group '%s' "
13029 "defined", attrGr->name);
13030 /*
13031 * NOTE: We will cut the reference to avoid further
13032 * confusion of the processor.
13033 * BADSPEC: The spec should define how to process in this case.
13034 */
13035 circ->attributes = NULL;
13036 circ->refItem = NULL;
13037 }
13038 }
13039}
13040
13041/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013042 * xmlSchemaAttrGrpFixup:
13043 * @attrgrpDecl: the schema attribute definition
13044 * @ctxt: the schema parser context
13045 * @name: the attribute name
13046 *
13047 * Fixes finish doing the computations on the attributes definitions
13048 */
13049static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013050xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013051 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013052{
13053 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013054 name = attrgrp->name;
13055 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013056 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013057 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013058 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013059
Daniel Veillardc0826a72004-08-10 14:17:33 +000013060 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13061 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013062 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013063 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013064 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013065 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13066 "ref", attrgrp->ref, attrgrp->refNs,
13067 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013068 return;
13069 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013070 attrgrp->refItem = ref;
13071 /*
13072 * Check for self reference!
13073 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013074 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013075 attrgrp->attributes = ref->attributes;
13076 attrgrp->attributeWildcard = ref->attributeWildcard;
13077 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013078}
13079
13080/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013081 * xmlSchemaAttrCheckValConstr:
13082 * @item: an schema attribute declaration/use
13083 * @ctxt: a schema parser context
13084 * @name: the name of the attribute
13085 *
13086 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013087 *
13088 * Fixes finish doing the computations on the attributes definitions
13089 */
13090static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013091xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13092 xmlSchemaParserCtxtPtr ctxt,
13093 const xmlChar * name ATTRIBUTE_UNUSED)
13094{
13095
13096 /*
13097 * a-props-correct
13098 * Schema Component Constraint: Attribute Declaration Properties Correct
13099 *
13100 * 2 if there is a {value constraint}, the canonical lexical
13101 * representation of its value must be ·valid· with respect
13102 * to the {type definition} as defined in String Valid (§3.14.4).
13103 */
13104
13105 if (item->defValue != NULL) {
13106 int ret;
13107 xmlNodePtr node;
13108 xmlSchemaTypePtr type;
13109
13110 if (item->subtypes == NULL) {
13111 xmlSchemaPErr(ctxt, item->node,
13112 XML_SCHEMAP_INTERNAL,
13113 "Internal error: xmlSchemaCheckAttrValConstr, "
13114 "type is missing... skipping validation of "
13115 "value constraint", NULL, NULL);
13116 return;
13117 }
13118
13119 /*
13120 * TODO: Try to avoid creating a new context.
13121 * TODO: This all is not very performant.
13122 */
13123 type = item->subtypes;
13124 /*
13125 * Ensure there's validation context.
13126 */
13127 if (ctxt->vctxt == NULL) {
13128 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13129 xmlSchemaPErr(ctxt, item->node,
13130 XML_SCHEMAP_INTERNAL,
13131 "Internal error: xmlSchemaCheckAttrValConstr, "
13132 "creating a new validation context.\n",
13133 NULL, NULL);
13134 return;
13135 }
13136 }
13137
13138 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13139 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13140 else
13141 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13142 ctxt->vctxt->node = node;
13143 ctxt->vctxt->cur = NULL;
13144 /*
13145 * NOTE: This call does not check the content nodes,
13146 * since they are not available:
13147 * facet->node is just the node holding the facet
13148 * definition, *not* the attribute holding the *value*
13149 * of the facet.
13150 */
13151 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13152 item->defValue, 0, 1, 1, 0);
13153 if (ret == 0) {
13154 /*
13155 * Store the computed value.
13156 */
13157 item->defVal = ctxt->vctxt->value;
13158 ctxt->vctxt->value = NULL;
13159 } else if (ret > 0) {
13160 if (ctxt != NULL) {
13161 xmlSchemaPSimpleTypeErr(ctxt,
13162 XML_SCHEMAP_A_PROPS_CORRECT_2,
13163 NULL, NULL, node,
13164 type, NULL, item->defValue,
13165 NULL, NULL, NULL);
13166 }
13167 } else if (ret < 0) {
13168 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13169 NULL, NULL, node,
13170 "Internal error: xmlSchemaAttrCheckValConstr, "
13171 "failed to validate the value constraint of the "
13172 "attribute decl/use against the type '%s'",
13173 type->name);
13174 }
13175 }
13176}
13177
13178#if 0 /* Not used yet. */
13179static int
13180xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13181 xmlSchemaElementPtr edecl)
13182{
13183 /*
13184 * TODO: 1 The values of the properties of an element declaration must be as
13185 * described in the property tableau in The Element Declaration Schema
13186 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13187 */
13188 /*
13189 * 2 If there is a {value constraint}, the canonical lexical
13190 * representation of its value must be ·valid· with respect to the {type
13191 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13192 *
13193 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13194 */
13195 /*
13196 * 3 If there is a non-·absent· {substitution group affiliation},
13197 * then {scope} must be global.
13198 *
13199 * NOTE: This is done in xmlSchemaParseElement.
13200 * TODO: Move it to this layer here.
13201 */
13202 /*
13203 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13204 * of the element declaration must be validly derived from the {type
13205 * definition} of the {substitution group affiliation}, given the value
13206 * of the {substitution group exclusions} of the {substitution group
13207 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13208 * (if the {type definition} is complex) or as defined in
13209 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13210 * simple).
13211 */
13212 /*
13213 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13214 * is or is derived from ID then there must not be a {value constraint}.
13215 * Note: The use of ID as a type definition for elements goes beyond
13216 * XML 1.0, and should be avoided if backwards compatibility is desired
13217 */
13218 /*
13219 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13220 * be possible to return to an element declaration by repeatedly following
13221 * the {substitution group affiliation} property.
13222 */
13223}
13224#endif
13225
13226/**
13227 * xmlSchemaCheckElemValConstr:
13228 * @item: an schema element declaration/particle
13229 * @ctxt: a schema parser context
13230 * @name: the name of the attribute
13231 *
13232 * Validates the value constraints of an element declaration.
13233 *
13234 * Fixes finish doing the computations on the element declarations.
13235 */
13236static void
13237xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13238 xmlSchemaParserCtxtPtr ctxt,
13239 const xmlChar * name ATTRIBUTE_UNUSED)
13240{
13241 if (decl->value != NULL) {
13242 int ret;
13243 xmlNodePtr node = NULL;
13244 xmlSchemaTypePtr type;
13245
13246 /*
13247 * 2 If there is a {value constraint}, the canonical lexical
13248 * representation of its value must be ·valid· with respect to the {type
13249 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13250 */
13251 if (decl->subtypes == NULL) {
13252 xmlSchemaPErr(ctxt, decl->node,
13253 XML_SCHEMAP_INTERNAL,
13254 "Internal error: xmlSchemaCheckElemValConstr, "
13255 "type is missing... skipping validation of "
13256 "the value constraint", NULL, NULL);
13257 return;
13258 }
13259 /*
13260 * Ensure there's a validation context.
13261 */
13262 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13263 return;
13264
13265 type = decl->subtypes;
13266
13267 if (decl->node != NULL) {
13268 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13269 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13270 else
13271 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13272 }
13273 ctxt->vctxt->node = node;
13274 ctxt->vctxt->cur = NULL;
13275 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13276 node);
13277 if (ret == 0) {
13278 /*
13279 * Consume the computed value.
13280 */
13281 decl->defVal = ctxt->vctxt->value;
13282 ctxt->vctxt->value = NULL;
13283 } else if (ret < 0) {
13284 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13285 NULL, NULL, node,
13286 "Internal error: xmlSchemaElemCheckValConstr, "
13287 "failed to validate the value constraint of the "
13288 "element declaration '%s'",
13289 decl->name);
13290 }
13291 }
13292}
13293
13294/**
13295 * xmlSchemaAttrFixup:
13296 * @item: an schema attribute declaration/use.
13297 * @ctxt: a schema parser context
13298 * @name: the name of the attribute
13299 *
13300 * Fixes finish doing the computations on attribute declarations/uses.
13301 */
13302static void
13303xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13304 xmlSchemaParserCtxtPtr ctxt,
13305 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013306{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013307 /*
13308 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013309 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013310 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013311 /*
13312 * The simple type definition corresponding to the <simpleType> element
13313 * information item in the [children], if present, otherwise the simple
13314 * type definition ·resolved· to by the ·actual value· of the type
13315 * [attribute], if present, otherwise the ·simple ur-type definition·.
13316 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013317 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013318 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013319 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13320 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013321 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013322 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013323 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013324
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013325 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13326 item->typeNs);
13327 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013328 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013329 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013330 NULL, (xmlSchemaTypePtr) item, item->node,
13331 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013332 XML_SCHEMA_TYPE_SIMPLE, NULL);
13333 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013334 item->subtypes = type;
13335
13336 } else if (item->ref != NULL) {
13337 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013338
Daniel Veillardc0826a72004-08-10 14:17:33 +000013339 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013340 * We have an attribute use here; assign the referenced
13341 * attribute declaration.
13342 */
13343 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013344 * TODO: Evaluate, what errors could occur if the declaration is not
13345 * found. It might be possible that the "typefixup" might crash if
13346 * no ref declaration was found.
13347 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013348 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13349 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013350 xmlSchemaPResCompAttrErr(ctxt,
13351 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013352 NULL, (xmlSchemaTypePtr) item, item->node,
13353 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013354 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013355 return;
13356 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013357 item->refDecl = decl;
13358 xmlSchemaAttrFixup(decl, ctxt, NULL);
13359
13360 item->subtypes = decl->subtypes;
13361 /*
13362 * Attribute Use Correct
13363 * au-props-correct.2: If the {attribute declaration} has a fixed
13364 * {value constraint}, then if the attribute use itself has a
13365 * {value constraint}, it must also be fixed and its value must match
13366 * that of the {attribute declaration}'s {value constraint}.
13367 */
13368 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13369 (item->defValue != NULL)) {
13370 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13371 (!xmlStrEqual(item->defValue, decl->defValue))) {
13372 xmlSchemaPCustomErr(ctxt,
13373 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13374 NULL, NULL, item->node,
13375 "The value constraint must be fixed "
13376 "and match the referenced attribute "
13377 "declarations's value constraint '%s'",
13378 decl->defValue);
13379 }
13380 /*
13381 * FUTURE: One should change the values of the attr. use
13382 * if ever validation should be attempted even if the
13383 * schema itself was not fully valid.
13384 */
13385 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013386 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013387 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13388 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013389}
13390
13391/**
13392 * xmlSchemaParse:
13393 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013394 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013395 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013396 * XML Shema struture which can be used to validate instances.
13397 * *WARNING* this interface is highly subject to change
13398 *
13399 * Returns the internal XML Schema structure built from the resource or
13400 * NULL in case of error
13401 */
13402xmlSchemaPtr
13403xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13404{
13405 xmlSchemaPtr ret = NULL;
13406 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013407 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013408 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013409
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013410 /*
13411 * This one is used if the schema to be parsed was specified via
13412 * the API; i.e. not automatically by the validated instance document.
13413 */
13414
Daniel Veillard4255d502002-04-16 15:50:10 +000013415 xmlSchemaInitTypes();
13416
Daniel Veillard6045c902002-10-09 21:13:59 +000013417 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013418 return (NULL);
13419
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013420 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013421 ctxt->counter = 0;
13422 ctxt->container = NULL;
13423
13424 /*
13425 * First step is to parse the input document into an DOM/Infoset
13426 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013427 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013428 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13429 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013430 if (doc == NULL) {
13431 xmlSchemaPErr(ctxt, NULL,
13432 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013433 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013434 ctxt->URL, NULL);
13435 return (NULL);
13436 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013437 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013438 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13439 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013440 if (doc == NULL) {
13441 xmlSchemaPErr(ctxt, NULL,
13442 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013443 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013444 NULL, NULL);
13445 return (NULL);
13446 }
13447 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013448 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013449 } else if (ctxt->doc != NULL) {
13450 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013451 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013452 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013453 xmlSchemaPErr(ctxt, NULL,
13454 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013455 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013456 NULL, NULL);
13457 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013458 }
13459
13460 /*
13461 * Then extract the root and Schema parse it
13462 */
13463 root = xmlDocGetRootElement(doc);
13464 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013465 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13466 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013467 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013468 if (!preserve) {
13469 xmlFreeDoc(doc);
13470 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013471 return (NULL);
13472 }
13473
13474 /*
13475 * Remove all the blank text nodes
13476 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013477 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013478
13479 /*
13480 * Then do the parsing for good
13481 */
13482 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013483 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013484 if (!preserve) {
13485 xmlFreeDoc(doc);
13486 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013487 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013488 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013489 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013490 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013491 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 ctxt->ctxtType = NULL;
13493 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013494 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013495 * Then fixup all attributes declarations
13496 */
13497 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13498
13499 /*
13500 * Then fixup all attributes group declarations
13501 */
13502 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13503 ctxt);
13504
13505 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013506 * Check attribute groups for circular references.
13507 */
13508 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13509 xmlSchemaCheckAttributeGroupCircular, ctxt);
13510
13511 /*
13512 * Then fixup all model group definitions.
13513 */
13514 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013515
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013516 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013517 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013518 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013519 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013520
13521 /*
13522 * Then fix references of element declaration; apply constraints.
13523 */
13524 xmlHashScanFull(ret->elemDecl,
13525 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013526
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013527 /*
13528 * Check model groups defnitions for circular references.
13529 */
13530 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13531 xmlSchemaCheckGroupDefCircular, ctxt);
13532
Daniel Veillard4255d502002-04-16 15:50:10 +000013533 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013534 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013535 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013536 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013537 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013538
13539 /*
13540 * Then check the defaults part of the type like facets values
13541 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013542 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013543
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013544 /*
13545 * Validate the value constraint of attribute declarations/uses.
13546 */
13547 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13548
13549 /*
13550 * Validate the value constraint of element declarations.
13551 */
13552 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13553
Daniel Veillardc0826a72004-08-10 14:17:33 +000013554
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013555 if (ctxt->nberrors != 0) {
13556 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013557 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013558 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013559 return (ret);
13560}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013561
Daniel Veillard4255d502002-04-16 15:50:10 +000013562/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013563 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013564 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013565 * @err: the error callback
13566 * @warn: the warning callback
13567 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013568 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013569 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013570 */
13571void
13572xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013573 xmlSchemaValidityErrorFunc err,
13574 xmlSchemaValidityWarningFunc warn, void *ctx)
13575{
Daniel Veillard4255d502002-04-16 15:50:10 +000013576 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013577 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013578 ctxt->error = err;
13579 ctxt->warning = warn;
13580 ctxt->userData = ctx;
13581}
13582
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013583/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013584 * xmlSchemaGetParserErrors:
13585 * @ctxt: a XMl-Schema parser context
13586 * @err: the error callback result
13587 * @warn: the warning callback result
13588 * @ctx: contextual data for the callbacks result
13589 *
13590 * Get the callback information used to handle errors for a parser context
13591 *
13592 * Returns -1 in case of failure, 0 otherwise
13593 */
13594int
13595xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13596 xmlSchemaValidityErrorFunc * err,
13597 xmlSchemaValidityWarningFunc * warn, void **ctx)
13598{
13599 if (ctxt == NULL)
13600 return(-1);
13601 if (err != NULL)
13602 *err = ctxt->error;
13603 if (warn != NULL)
13604 *warn = ctxt->warning;
13605 if (ctx != NULL)
13606 *ctx = ctxt->userData;
13607 return(0);
13608}
13609
13610/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013611 * xmlSchemaFacetTypeToString:
13612 * @type: the facet type
13613 *
13614 * Convert the xmlSchemaTypeType to a char string.
13615 *
13616 * Returns the char string representation of the facet type if the
13617 * type is a facet and an "Internal Error" string otherwise.
13618 */
13619static const char *
13620xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13621{
13622 switch (type) {
13623 case XML_SCHEMA_FACET_PATTERN:
13624 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013625 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013626 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013627 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013628 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013629 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013630 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013631 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013632 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013634 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013635 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013636 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013637 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013638 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013639 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013640 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013641 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013642 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013643 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013644 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013645 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013646 return ("fractionDigits");
13647 default:
13648 break;
13649 }
13650 return ("Internal Error");
13651}
13652
Daniel Veillardc0826a72004-08-10 14:17:33 +000013653
Daniel Veillardc0826a72004-08-10 14:17:33 +000013654
13655static int
13656xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13657{
13658 xmlSchemaTypePtr anc;
13659
13660 /*
13661 * The normalization type can be changed only for types which are derived
13662 * from xsd:string.
13663 */
13664 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013665 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013666 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013667 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13668 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013669 else {
13670 /*
13671 * For all ·atomic· datatypes other than string (and types ·derived·
13672 * by ·restriction· from it) the value of whiteSpace is fixed to
13673 * collapse
13674 */
13675 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13676 }
13677 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13678 /*
13679 * For list types the facet "whiteSpace" is fixed to "collapse".
13680 */
13681 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13682 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13683 return (-1);
13684 } else if (type->facetSet != NULL) {
13685 xmlSchemaTypePtr anyST;
13686 xmlSchemaFacetLinkPtr lin;
13687
13688 /*
13689 * Atomic types.
13690 */
13691 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13692 anc = type->baseType;
13693 do {
13694 /*
13695 * For all ·atomic· datatypes other than string (and types ·derived·
13696 * by ·restriction· from it) the value of whiteSpace is fixed to
13697 * collapse
13698 */
13699 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13700 (anc->builtInType == XML_SCHEMAS_STRING)) {
13701
13702 lin = type->facetSet;
13703 do {
13704 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13705 if (lin->facet->whitespace ==
13706 XML_SCHEMAS_FACET_COLLAPSE) {
13707 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13708 } else if (lin->facet->whitespace ==
13709 XML_SCHEMAS_FACET_REPLACE) {
13710 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13711 } else
13712 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13713 break;
13714 }
13715 lin = lin->next;
13716 } while (lin != NULL);
13717 break;
13718 }
13719 anc = anc->baseType;
13720 } while (anc != anyST);
13721 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13722 }
13723 return (-1);
13724}
13725
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013726/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013727 * xmlSchemaValidateFacetsInternal:
13728 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013729 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013730 * @facets: the list of facets to check
13731 * @value: the lexical repr of the value to validate
13732 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013733 * @fireErrors: if 0, only internal errors will be fired;
13734 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013735 *
13736 * Check a value against all facet conditions
13737 *
13738 * Returns 0 if the element is schemas valid, a positive error code
13739 * number otherwise and -1 in case of internal or API error.
13740 */
13741static int
13742xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013743 xmlSchemaTypePtr type,
13744 const xmlChar * value,
13745 unsigned long length,
13746 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013747{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013748 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013749 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013750 xmlSchemaTypePtr biType; /* The build-in type. */
13751 xmlSchemaTypePtr tmpType;
13752 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013753 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013754 xmlSchemaFacetPtr facet;
13755 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013756
Daniel Veillardc0826a72004-08-10 14:17:33 +000013757#ifdef DEBUG_UNION_VALIDATION
13758 printf("Facets of type: '%s'\n", (const char *) type->name);
13759 printf(" fireErrors: %d\n", fireErrors);
13760#endif
13761
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013762 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013763 /*
13764 * NOTE: Do not jump away, if the facetSet of the given type is
13765 * empty: until now, "pattern" facets of the *base types* need to
13766 * be checked as well.
13767 */
13768 biType = type->baseType;
13769 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13770 biType = biType->baseType;
13771 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013772 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013773 "Internal error: xmlSchemaValidateFacetsInternal, "
13774 "the base type axis of the given type '%s' does not resolve to "
13775 "a built-in type.\n",
13776 type->name, NULL);
13777 return (-1);
13778 }
13779
13780 if (type->facetSet != NULL) {
13781 facetLink = type->facetSet;
13782 while (facetLink != NULL) {
13783 facet = facetLink->facet;
13784 /*
13785 * Skip the pattern "whiteSpace": it is used to
13786 * format the character content beforehand.
13787 */
13788 switch (facet->type) {
13789 case XML_SCHEMA_FACET_WHITESPACE:
13790 case XML_SCHEMA_FACET_PATTERN:
13791 case XML_SCHEMA_FACET_ENUMERATION:
13792 break;
13793 case XML_SCHEMA_FACET_LENGTH:
13794 case XML_SCHEMA_FACET_MINLENGTH:
13795 case XML_SCHEMA_FACET_MAXLENGTH:
13796 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13797 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13798 value, length, 0);
13799 len = length;
13800 } else
13801 ret = xmlSchemaValidateLengthFacet(biType, facet,
13802 value, ctxt->value, &len);
13803 break;
13804 default:
13805 ret = xmlSchemaValidateFacet(biType, facet, value,
13806 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013809 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 "Internal error: xmlSchemaValidateFacetsInternal, "
13811 "validating facet of type '%s'.\n",
13812 type->name, NULL);
13813 break;
13814 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013815 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013816 type, facet, NULL, NULL, NULL, NULL);
13817 }
13818
13819 facetLink = facetLink->next;
13820 }
13821 if (ret >= 0) {
13822 /*
13823 * Process enumerations.
13824 */
13825 retFacet = 0;
13826 facetLink = type->facetSet;
13827 while (facetLink != NULL) {
13828 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13829 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13830 value, ctxt->value);
13831 if (retFacet <= 0)
13832 break;
13833 }
13834 facetLink = facetLink->next;
13835 }
13836 if (retFacet > 0) {
13837 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13838 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013839 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013840 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13841 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013842 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 "Internal error: xmlSchemaValidateFacetsInternal, "
13844 "validating facet of type '%s'.\n",
13845 BAD_CAST "enumeration", NULL);
13846 ret = -1;
13847 }
13848 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013849 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013850 if (ret >= 0) {
13851 /*
13852 * Process patters. Pattern facets are ORed at type level
13853 * and ANDed if derived. Walk the base type axis.
13854 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013855 tmpType = type;
13856 facet = NULL;
13857 do {
13858 retFacet = 0;
13859 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013860 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013861 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13862 continue;
13863 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13864 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013865 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013866 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013867 else if (retFacet < 0) {
13868 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13869 "Internal error: xmlSchemaValidateFacetsInternal, "
13870 "validating 'pattern' facet '%s' of type '%s'.\n",
13871 facetLink->facet->value, tmpType->name);
13872 ret = -1;
13873 break;
13874 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013875 /* Save the last non-validating facet. */
13876 facet = facetLink->facet;
13877 }
13878 if (retFacet != 0)
13879 break;
13880 tmpType = tmpType->baseType;
13881 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013882 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013883 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13884 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013885 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013886 NULL, NULL, NULL, NULL);
13887 }
13888 }
13889 }
13890
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013891 return (ret);
13892}
13893
Daniel Veillard4255d502002-04-16 15:50:10 +000013894/************************************************************************
13895 * *
13896 * Simple type validation *
13897 * *
13898 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013899
Daniel Veillard4255d502002-04-16 15:50:10 +000013900
13901/************************************************************************
13902 * *
13903 * DOM Validation code *
13904 * *
13905 ************************************************************************/
13906
Daniel Veillard4255d502002-04-16 15:50:10 +000013907static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013908 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013909 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013910static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013911 xmlSchemaTypePtr type,
13912 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013913
Daniel Veillard3646d642004-06-02 19:19:14 +000013914
13915/**
13916 * xmlSchemaFreeAttrStates:
13917 * @state: a list of attribute states
13918 *
13919 * Free the given list of attribute states
13920 *
13921 */
13922static void
13923xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13924{
13925 xmlSchemaAttrStatePtr tmp;
13926 while (state != NULL) {
13927 tmp = state;
13928 state = state->next;
13929 xmlFree(tmp);
13930 }
13931}
13932
Daniel Veillard4255d502002-04-16 15:50:10 +000013933/**
13934 * xmlSchemaRegisterAttributes:
13935 * @ctxt: a schema validation context
13936 * @attrs: a list of attributes
13937 *
13938 * Register the list of attributes as the set to be validated on that element
13939 *
13940 * Returns -1 in case of error, 0 otherwise
13941 */
13942static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013943xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
13944{
Daniel Veillard3646d642004-06-02 19:19:14 +000013945 xmlSchemaAttrStatePtr tmp;
13946
13947 ctxt->attr = NULL;
13948 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013949 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013950 if ((attrs->ns != NULL) &&
13951 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
13952 attrs = attrs->next;
13953 continue;
13954 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013955 tmp = (xmlSchemaAttrStatePtr)
13956 xmlMalloc(sizeof(xmlSchemaAttrState));
13957 if (tmp == NULL) {
13958 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
13959 return (-1);
13960 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013961 tmp->attr = attrs;
13962 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
13963 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013964 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013965 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013966 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013967 else
13968 ctxt->attrTop->next = tmp;
13969 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013970 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013971 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013972 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000013973}
13974
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013975#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000013976/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013977 * xmlSchemaValidateCheckNodeList
13978 * @nodelist: the list of nodes
13979 *
13980 * Check the node list is only made of text nodes and entities pointing
13981 * to text nodes
13982 *
13983 * Returns 1 if true, 0 if false and -1 in case of error
13984 */
13985static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013986xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
13987{
Daniel Veillard4255d502002-04-16 15:50:10 +000013988 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013989 if (nodelist->type == XML_ENTITY_REF_NODE) {
13990 TODO /* implement recursion in the entity content */
13991 }
13992 if ((nodelist->type != XML_TEXT_NODE) &&
13993 (nodelist->type != XML_COMMENT_NODE) &&
13994 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000013995 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013996 return (0);
13997 }
13998 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000013999 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014000 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014001}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014002#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014003
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014004static void
14005xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14006{
14007 int i, nbItems;
14008 xmlSchemaTypePtr item, *items;
14009
14010
14011 /*
14012 * During the Assemble of the schema ctxt->curItems has
14013 * been filled with the relevant new items. Fix those up.
14014 */
14015 nbItems = ctxt->assemble->nbItems;
14016 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14017
14018 for (i = 0; i < nbItems; i++) {
14019 item = items[i];
14020 switch (item->type) {
14021 case XML_SCHEMA_TYPE_ATTRIBUTE:
14022 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14023 break;
14024 case XML_SCHEMA_TYPE_ELEMENT:
14025 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14026 NULL, NULL, NULL);
14027 break;
14028 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14029 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14030 ctxt, NULL);
14031 break;
14032 case XML_SCHEMA_TYPE_GROUP:
14033 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14034 default:
14035 break;
14036 }
14037 }
14038 /*
14039 * Circularity checks.
14040 */
14041 for (i = 0; i < nbItems; i++) {
14042 item = items[i];
14043 switch (item->type) {
14044 case XML_SCHEMA_TYPE_GROUP:
14045 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14046 break;
14047 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14048 xmlSchemaCheckAttributeGroupCircular(
14049 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14050 break;
14051 default:
14052 break;
14053 }
14054 }
14055 /*
14056 * Fixup for all other item.
14057 * TODO: Hmm, not sure if starting from complex/simple types,
14058 * all subsequent items will be reached.
14059 */
14060 for (i = 0; i < nbItems; i++) {
14061 item = items[i];
14062 switch (item->type) {
14063 case XML_SCHEMA_TYPE_SIMPLE:
14064 case XML_SCHEMA_TYPE_COMPLEX:
14065 xmlSchemaTypeFixup(item, ctxt, NULL);
14066 break;
14067 default:
14068 break;
14069 }
14070 }
14071 /*
14072 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014073 * hold by simple type components only (and
14074 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014075 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014076 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014077 for (i = 0; i < nbItems; i++) {
14078 item = items[i];
14079 switch (item->type) {
14080 case XML_SCHEMA_TYPE_SIMPLE:
14081 case XML_SCHEMA_TYPE_COMPLEX:
14082 xmlSchemaCheckDefaults(item, ctxt, NULL);
14083 break;
14084 default:
14085 break;
14086 }
14087 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014088 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014089 /*
14090 * Build the content model for complex types.
14091 */
14092 for (i = 0; i < nbItems; i++) {
14093 item = items[i];
14094 switch (item->type) {
14095 case XML_SCHEMA_TYPE_COMPLEX:
14096 xmlSchemaBuildContentModel(item, ctxt, NULL);
14097 break;
14098 default:
14099 break;
14100 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014101 }
14102 /*
14103 * Validate value contraint values.
14104 */
14105 for (i = 0; i < nbItems; i++) {
14106 item = items[i];
14107 switch (item->type) {
14108 case XML_SCHEMA_TYPE_ATTRIBUTE:
14109 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14110 break;
14111 case XML_SCHEMA_TYPE_ELEMENT:
14112 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14113 break;
14114 default:
14115 break;
14116 }
14117 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014118}
14119
14120/**
14121 * xmlSchemaAssembleByLocation:
14122 * @pctxt: a schema parser context
14123 * @vctxt: a schema validation context
14124 * @schema: the existing schema
14125 * @node: the node that fired the assembling
14126 * @nsName: the namespace name of the new schema
14127 * @location: the location of the schema
14128 *
14129 * Expands an existing schema by an additional schema.
14130 *
14131 * Returns 0 if the new schema is correct, a positive error code
14132 * number otherwise and -1 in case of an internal or API error.
14133 */
14134static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014135xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14136 xmlSchemaPtr schema,
14137 xmlNodePtr node,
14138 const xmlChar *nsName,
14139 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014140{
14141 const xmlChar *targetNs, *oldtns;
14142 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014143 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014144 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014145 xmlSchemaParserCtxtPtr pctxt;
14146
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014147 /*
14148 * This should be used:
14149 * 1. on <import>(s)
14150 * 2. if requested by the validated instance
14151 * 3. if requested via the API
14152 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014153 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014154 return (-1);
14155 /*
14156 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014157 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 if ((vctxt->pctxt == NULL) &&
14159 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14160 xmlSchemaVErr(vctxt, node,
14161 XML_SCHEMAV_INTERNAL,
14162 "Internal error: xmlSchemaAssembleByLocation, "
14163 "failed to create a temp. parser context.\n",
14164 NULL, NULL);
14165 return (-1);
14166 }
14167 pctxt = vctxt->pctxt;
14168 /*
14169 * Set the counter to produce unique names for anonymous items.
14170 */
14171 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014172 /*
14173 * Acquire the schema document.
14174 */
14175 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14176 nsName, location, &doc, &targetNs, 0);
14177 if (ret != 0) {
14178 if (doc != NULL)
14179 xmlFreeDoc(doc);
14180 } else if (doc != NULL) {
14181 docElem = xmlDocGetRootElement(doc);
14182 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014183 * Create new assemble info.
14184 */
14185 if (pctxt->assemble == NULL) {
14186 pctxt->assemble = xmlSchemaNewAssemble();
14187 if (pctxt->assemble == NULL) {
14188 xmlSchemaVErrMemory(vctxt,
14189 "Memory error: xmlSchemaAssembleByLocation, "
14190 "allocating assemble info", NULL);
14191 xmlFreeDoc(doc);
14192 return (-1);
14193 }
14194 }
14195 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014196 * Save and reset the context & schema.
14197 */
14198 oldflags = schema->flags;
14199 oldtns = schema->targetNamespace;
14200 olddoc = schema->doc;
14201
14202 xmlSchemaClearSchemaDefaults(schema);
14203 schema->targetNamespace = targetNs;
14204 /* schema->nbCurItems = 0; */
14205 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014206 pctxt->ctxtType = NULL;
14207 pctxt->parentItem = NULL;
14208
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014209 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14210 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014211 xmlSchemaPostSchemaAssembleFixup(pctxt);
14212 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014213 * Set the counter of items.
14214 */
14215 schema->counter = pctxt->counter;
14216 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014217 * Free the list of assembled components.
14218 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014219 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014220 /*
14221 * Restore the context & schema.
14222 */
14223 schema->flags = oldflags;
14224 schema->targetNamespace = oldtns;
14225 schema->doc = olddoc;
14226 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014227 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014228 return (ret);
14229}
14230
14231/**
14232 * xmlSchemaAssembleByXSIAttr:
14233 * @vctxt: a schema validation context
14234 * @xsiAttr: an xsi attribute
14235 * @noNamespace: whether a schema with no target namespace is exptected
14236 *
14237 * Expands an existing schema by an additional schema using
14238 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14239 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14240 * must be set to 1.
14241 *
14242 * Returns 0 if the new schema is correct, a positive error code
14243 * number otherwise and -1 in case of an internal or API error.
14244 */
14245static int
14246xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14247 xmlAttrPtr xsiAttr,
14248 int noNamespace)
14249{
14250 xmlChar *value;
14251 const xmlChar *cur, *end;
14252 const xmlChar *nsname = NULL, *location;
14253 int count = 0;
14254 int ret = 0;
14255
14256 if (xsiAttr == NULL) {
14257 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14258 NULL, NULL,
14259 "Internal error: xmlSchemaAssembleByXSIAttr, "
14260 "bad arguments", NULL);
14261 return (-1);
14262 }
14263 /*
14264 * Parse the value; we will assume an even number of values
14265 * to be given (this is how Xerces and XSV work).
14266 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014267 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014268 cur = value;
14269 do {
14270 if (noNamespace != 1) {
14271 /*
14272 * Get the namespace name.
14273 */
14274 while (IS_BLANK_CH(*cur))
14275 cur++;
14276 end = cur;
14277 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14278 end++;
14279 if (end == cur)
14280 break;
14281 count++;
14282 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14283 cur = end;
14284 }
14285 /*
14286 * Get the URI.
14287 */
14288 while (IS_BLANK_CH(*cur))
14289 cur++;
14290 end = cur;
14291 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14292 end++;
14293 if (end == cur)
14294 break;
14295 count++;
14296 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014297 cur = end;
14298 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014299 xsiAttr->parent, nsname, location);
14300 if (ret == -1) {
14301 xmlSchemaVCustomErr(vctxt,
14302 XML_SCHEMAV_INTERNAL,
14303 (xmlNodePtr) xsiAttr, NULL,
14304 "Internal error: xmlSchemaAssembleByXSIAttr, "
14305 "assembling schemata", NULL);
14306 if (value != NULL)
14307 xmlFree(value);
14308 return (-1);
14309 }
14310 } while (*cur != 0);
14311 if (value != NULL)
14312 xmlFree(value);
14313 return (ret);
14314}
14315
14316/**
14317 * xmlSchemaAssembleByXSIElem:
14318 * @vctxt: a schema validation context
14319 * @elem: an element node possibly holding xsi attributes
14320 * @noNamespace: whether a schema with no target namespace is exptected
14321 *
14322 * Assembles an existing schema by an additional schema using
14323 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14324 * of the given @elem.
14325 *
14326 * Returns 0 if the new schema is correct, a positive error code
14327 * number otherwise and -1 in case of an internal or API error.
14328 */
14329static int
14330xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14331 xmlNodePtr elem)
14332{
14333 int ret = 0, retNs = 0;
14334 xmlAttrPtr attr;
14335
14336 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14337 if (attr != NULL) {
14338 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14339 if (retNs == -1)
14340 return (-1);
14341 }
14342 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14343 if (attr != NULL) {
14344 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14345 if (ret == -1)
14346 return (-1);
14347 }
14348 if (retNs != 0)
14349 return (retNs);
14350 else
14351 return (ret);
14352}
14353
Daniel Veillard4255d502002-04-16 15:50:10 +000014354/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014355 * xmlSchemaValidateCallback:
14356 * @ctxt: a schema validation context
14357 * @name: the name of the element detected (might be NULL)
14358 * @type: the type
14359 *
14360 * A transition has been made in the automata associated to an element
14361 * content model
14362 */
14363static void
14364xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014365 const xmlChar * name ATTRIBUTE_UNUSED,
14366 xmlSchemaTypePtr type, xmlNodePtr node)
14367{
Daniel Veillard4255d502002-04-16 15:50:10 +000014368 xmlSchemaTypePtr oldtype = ctxt->type;
14369 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014370
Daniel Veillard4255d502002-04-16 15:50:10 +000014371#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014372 xmlGenericError(xmlGenericErrorContext,
14373 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014374 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014375#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014376 /*
14377 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14378 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014379 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014380 ctxt->node = node;
14381 ctxt->cur = node->children;
14382 /*
14383 * Assemble new schemata using xsi.
14384 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014385 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014386 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014387
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014388 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14389 if (ret == -1) {
14390 xmlSchemaVCustomErr(ctxt,
14391 XML_SCHEMAV_INTERNAL,
14392 ctxt->node, NULL,
14393 "Internal error: xmlSchemaValidateElement, "
14394 "assembling schema by xsi", NULL);
14395 return;
14396 }
14397 /*
14398 * NOTE: We won't react on schema parser errors here.
14399 * TODO: But a warning would be nice.
14400 */
14401 }
14402 switch (type->type) {
14403 case XML_SCHEMA_TYPE_ELEMENT: {
14404 /*
14405 * NOTE: The build of the content model
14406 * (xmlSchemaBuildAContentModel) ensures that the element
14407 * declaration (and not a reference to it) will be given.
14408 */
14409 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14410 /*
14411 * This is paranoid coding ;-)... it should not
14412 * happen here any more.
14413 */
14414 xmlSchemaVCustomErr(ctxt,
14415 XML_SCHEMAV_INTERNAL,
14416 node, NULL,
14417 "Internal error: xmlSchemaValidateCallback, "
14418 "element declaration 'reference' encountered, "
14419 "but an element declaration was expected",
14420 NULL);
14421 return;
14422 }
14423 xmlSchemaValidateElementByDeclaration(ctxt,
14424 (xmlSchemaElementPtr) type);
14425 break;
14426 }
14427 case XML_SCHEMA_TYPE_ANY:
14428 xmlSchemaValidateElementByWildcard(ctxt, type);
14429 break;
14430 default:
14431 break;
14432 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014433 ctxt->type = oldtype;
14434 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014435}
Daniel Veillard4255d502002-04-16 15:50:10 +000014436
Daniel Veillard01fa6152004-06-29 17:04:39 +000014437/**
14438 * xmlSchemaValidateSimpleTypeValue:
14439 * @ctxt: a schema validation context
14440 * @value: the value to be validated
14441 * @fireErrors: shall errors be reported?
14442 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014443 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014444 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014445 *
14446 * Validates a value by the given type (user derived or built-in).
14447 *
14448 * Returns 0 if the value is valid, a positive error code
14449 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014450 */
14451static int
14452xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014453 xmlSchemaTypePtr type,
14454 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014455 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014456 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014457 int normalize,
14458 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014459{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014460 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014461 int ret = 0;
14462 xmlChar *normValue = NULL;
14463 int wtsp;
14464
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014465 node = ctxt->node;
14466 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014467 wtsp = ctxt->valueWS;
14468 /*
14469 * Normalize the value.
14470 */
14471 if (normalize &&
14472 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14473 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14474
14475 if ((norm != -1) && (norm > ctxt->valueWS)) {
14476 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14477 normValue = xmlSchemaCollapseString(value);
14478 else
14479 normValue = xmlSchemaWhiteSpaceReplace(value);
14480 ctxt->valueWS = norm;
14481 if (normValue != NULL)
14482 value = (const xmlChar *) normValue;
14483 }
14484 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014485 /*
14486 * The nodes of a content must be checked only once,
14487 * this is not working since list types will fire this
14488 * multiple times.
14489 */
14490 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14491 xmlNodePtr cur = ctxt->cur;
14492
14493 do {
14494 switch (cur->type) {
14495 case XML_TEXT_NODE:
14496 case XML_CDATA_SECTION_NODE:
14497 case XML_PI_NODE:
14498 case XML_COMMENT_NODE:
14499 case XML_XINCLUDE_START:
14500 case XML_XINCLUDE_END:
14501 break;
14502 case XML_ENTITY_REF_NODE:
14503 case XML_ENTITY_NODE:
14504 /* TODO: Scour the entities for illegal nodes. */
14505 TODO break;
14506 case XML_ELEMENT_NODE: {
14507 /* NOTE: Changed to an internal error, since the
14508 * existence of an element node will be already checked in
14509 * xmlSchemaValidateElementBySimpleType and in
14510 * xmlSchemaValidateElementByComplexType.
14511 */
14512 xmlSchemaVCustomErr(ctxt,
14513 XML_SCHEMAV_INTERNAL,
14514 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14515 node, type,
14516 "Element '%s' found in simple type content",
14517 cur->name);
14518 return (XML_SCHEMAV_INTERNAL);
14519 }
14520 case XML_ATTRIBUTE_NODE:
14521 case XML_DOCUMENT_NODE:
14522 case XML_DOCUMENT_TYPE_NODE:
14523 case XML_DOCUMENT_FRAG_NODE:
14524 case XML_NOTATION_NODE:
14525 case XML_HTML_DOCUMENT_NODE:
14526 case XML_DTD_NODE:
14527 case XML_ELEMENT_DECL:
14528 case XML_ATTRIBUTE_DECL:
14529 case XML_ENTITY_DECL:
14530 case XML_NAMESPACE_DECL:
14531#ifdef LIBXML_DOCB_ENABLED
14532 case XML_DOCB_DOCUMENT_NODE:
14533#endif
14534 xmlSchemaVCustomErr(ctxt,
14535 XML_SCHEMAV_INTERNAL,
14536 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14537 node, NULL,
14538 "Node of unexpected type found in simple type content",
14539 NULL);
14540 return (XML_SCHEMAV_INTERNAL);
14541 }
14542 cur = cur->next;
14543 } while (cur != NULL);
14544 }
14545
William M. Brack2f2a6632004-08-20 23:09:47 +000014546 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14547 xmlSchemaTypePtr base, anyType;
14548
14549 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14550
14551 base = type->baseType;
14552 while ((base != NULL) &&
14553 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14554 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14555 (base != anyType)) {
14556 base = base->baseType;
14557 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014558 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014559 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014560 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014561 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14562 "validating complex type '%s'\n",
14563 type->name, NULL);
14564 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14565 /*
14566 * Check facets.
14567 */
14568 /*
14569 * This is somehow not nice, since if an error occurs
14570 * the reported type will be the complex type; the spec
14571 * wants a simple type to be created on the complex type
14572 * if it has a simple content. For now we have to live with
14573 * it.
14574 */
14575 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14576 value, 0, fireErrors);
14577 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014578 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014579 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14580 "validating facets of complex type '%s'\n",
14581 type->name, NULL);
14582 } else if (ret > 0) {
14583 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014584 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014585 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014586 }
14587 }
14588 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014589
14590 if (ctxt->value != NULL) {
14591 xmlSchemaFreeValue(ctxt->value);
14592 ctxt->value = NULL;
14593 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014594 /*
14595 * STREAM-READ-CHILDREN.
14596 */
14597 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014598 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014599 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14600 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14601 else
14602 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014603 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014604 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014605 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014606 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014607 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014608 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014609 }
14610 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14611 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14612 * a literal in the ·lexical space· of {base type definition}
14613 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014614 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014615 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014616 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014617 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014618 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014619 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014620 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014621 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014622 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014623 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014624 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014626 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014627 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014628 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14629 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014630 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014631 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014632 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014633 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014634 type->name, NULL);
14635 } else if (ret > 0) {
14636 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014637 /*
14638 Disabled, since the facet validation already reports errors.
14639 if (fireErrors)
14640 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14641 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014642 }
14643 }
14644 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14645
14646 xmlSchemaTypePtr tmpType;
14647 const xmlChar *cur, *end;
14648 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014649 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014650
14651 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14652 * of white space separated tokens, each of which ·match·es a literal
14653 * in the ·lexical space· of {item type definition}
14654 */
14655
Daniel Veillardc0826a72004-08-10 14:17:33 +000014656 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014657 cur = value;
14658 do {
14659 while (IS_BLANK_CH(*cur))
14660 cur++;
14661 end = cur;
14662 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14663 end++;
14664 if (end == cur)
14665 break;
14666 tmp = xmlStrndup(cur, end - cur);
14667 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014668 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014669 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014670 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014671 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014672 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14673 "validating an item of list simple type '%s'\n",
14674 type->name, NULL);
14675 break;
14676 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014677 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014678 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014679 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014680 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014681 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 cur = end;
14683 } while (*cur != 0);
14684 /*
14685 * Check facets.
14686 */
14687 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014688 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014689 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014690 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014691 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014692 } else if ((ret == 0) && (applyFacets)) {
14693 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14694 value, len, fireErrors);
14695 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014696 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014697 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14698 "validating facets of list simple type '%s'\n",
14699 type->name, NULL);
14700 } else if (ret > 0) {
14701 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014703 Disabled, since the facet validation already reports errors.
14704 if (fireErrors)
14705 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014706 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014707 }
14708
Daniel Veillard01fa6152004-06-29 17:04:39 +000014709 }
14710 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14711 xmlSchemaTypeLinkPtr memberLink;
14712
14713 /*
14714 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14715 * not apply directly; however, the normalization behavior of ·union·
14716 * types is controlled by the value of whiteSpace on that one of the
14717 * ·memberTypes· against which the ·union· is successfully validated.
14718 *
14719 * This means that the value is normalized by the first validating
14720 * member type, then the facets of the union type are applied. This
14721 * needs changing of the value!
14722 */
14723
14724 /*
14725 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14726 * literal in the ·lexical space· of at least one member of
14727 * {member type definitions}
14728 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014729#ifdef DEBUG_UNION_VALIDATION
14730 printf("Union ST : '%s'\n", (const char *) type->name);
14731 printf(" fireErrors : %d\n", fireErrors);
14732 printf(" applyFacets: %d\n", applyFacets);
14733#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014734 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14735 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014736 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014737 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014738 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 type->name, NULL);
14740 ret = -1;
14741 }
14742 if (ret == 0) {
14743 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014744 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14745 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014746 if ((ret <= 0) || (ret == 0))
14747 break;
14748 memberLink = memberLink->next;
14749 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014750 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014751 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014752 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014753 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014754 type->name, NULL);
14755 } else if (ret > 0) {
14756 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014757 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014758 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014759 }
14760 }
14761 /*
14762 * Apply facets (pattern, enumeration).
14763 */
14764 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14765 int mws;
14766 /*
14767 * The normalization behavior of ·union· types is controlled by
14768 * the value of whiteSpace on that one of the ·memberTypes·
14769 * against which the ·union· is successfully validated.
14770 */
14771 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014772 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014773 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14774 "the value was already normalized for the union simple "
14775 "type '%s'.\n", type->name, NULL);
14776 }
14777 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14778 if (mws > ctxt->valueWS) {
14779 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14780 normValue = xmlSchemaCollapseString(value);
14781 else
14782 normValue = xmlSchemaWhiteSpaceReplace(value);
14783 if (normValue != NULL)
14784 value = (const xmlChar *) normValue;
14785 }
14786
14787 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14788 value, 0, fireErrors);
14789 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014790 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014791 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14792 "validating facets of union simple type '%s'\n",
14793 type->name, NULL);
14794 } else if (ret > 0) {
14795 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14796 /*
14797 if (fireErrors)
14798 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14799 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014800 }
14801 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014802 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014803 ctxt->valueWS = wtsp;
14804 if (normValue != NULL)
14805 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014806 return (ret);
14807}
14808
14809/**
14810 * xmlSchemaValidateSimpleTypeElement:
14811 * @ctxt: a schema validation context
14812 * @node: the element node to be validated.
14813 *
14814 * Validate the element against a simple type.
14815 *
14816 * Returns 0 if the element is valid, a positive error code
14817 * number otherwise and -1 in case of an internal or API error.
14818 */
14819static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014820xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014821 xmlSchemaTypePtr type,
14822 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014823{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014824 xmlSchemaTypePtr oldtype;
14825 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014826 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014827 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014828 int ret = 0, retval = 0;
14829
Daniel Veillard01fa6152004-06-29 17:04:39 +000014830 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014831 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14832 "Internal error: xmlSchemaValidateElementBySimpleType, "
14833 "bad arguments", NULL);
14834 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014835 }
14836
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014837 oldtype = ctxt->type;
14838 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014839 /*
14840 * cvc-type: 3.1.2 The element information item must have no element
14841 * information item [children].
14842 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014843 /*
14844 * STREAM: Child nodes are processed.
14845 */
14846 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014847 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014848 /*
14849 * TODO: Entities, will they produce elements as well?
14850 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014851 if (cur->type == XML_ELEMENT_NODE) {
14852 xmlSchemaVCustomErr(ctxt,
14853 XML_SCHEMAV_CVC_TYPE_3_1_2,
14854 node, type,
14855 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014856 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014857 }
14858 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014859 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014860
Daniel Veillard01fa6152004-06-29 17:04:39 +000014861 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014862 * cvc-type 3.1.1:
14863 *
14864 * The attributes of must be empty, excepting those whose namespace name
14865 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14866 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014867 */
14868 /*
14869 * STREAM: Attribute nodes are processed.
14870 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014871 attr = node->properties;
14872 while (attr != NULL) {
14873 if ((attr->ns == NULL) ||
14874 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14875 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14876 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14877 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14878 (!xmlStrEqual
14879 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014880 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014881 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14882 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014883 }
14884 attr = attr->next;
14885 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014886 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014887 * This will skip validation if the type is 'anySimpleType' and
14888 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014889 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014890 if ((valSimpleContent == 1) &&
14891 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14892 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014893 xmlChar *value;
14894
14895 value = xmlNodeGetContent(node);
14896 /*
14897 * NOTE: This call will not check the content nodes, since
14898 * this should be checked here already.
14899 */
14900 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14901 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014902 if (value != NULL)
14903 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014904 if (retval != 0)
14905 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014906 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014907 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014908 return (ret);
14909}
Daniel Veillard4255d502002-04-16 15:50:10 +000014910
14911/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014912 * xmlSchemaValQNameAcquire:
14913 * @value: the lexical represantation of the QName value
14914 * @node: the node to search for the corresponding namespace declaration
14915 * @nsName: the resulting namespace name if found
14916 *
14917 * Checks that a value conforms to the lexical space of the type QName;
14918 * if valid, the corresponding namespace name is searched and retured
14919 * as a copy in @nsName. The local name is returned in @localName as
14920 * a copy.
14921 *
14922 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14923 * namespace declaration was found in scope; -1 in case of an internal or
14924 * API error.
14925 */
14926static int
14927xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14928 xmlChar **nsName, xmlChar **localName)
14929{
14930 int ret;
14931 xmlChar *local = NULL;
14932
14933 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14934 return (-1);
14935 *nsName = NULL;
14936 *localName = NULL;
14937 ret = xmlValidateQName(value, 1);
14938 if (ret == 0) {
14939 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014940 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014941
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014942 /*
14943 * NOTE: xmlSplitQName2 will return a duplicated
14944 * string.
14945 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014946 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014947 if (local == NULL)
14948 local = xmlStrdup(value);
14949 ns = xmlSearchNs(node->doc, node, prefix);
14950 /*
14951 * A namespace need not to be found if the prefix is NULL.
14952 */
14953 if (ns != NULL) {
14954 /*
14955 * TODO: Is it necessary to duplicate the URI here?
14956 */
14957 *nsName = xmlStrdup(ns->href);
14958 } else if (prefix != NULL) {
14959 xmlFree(prefix);
14960 if (local != NULL)
14961 xmlFree(local);
14962 return (2);
14963 }
14964 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014965 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014966 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014967 } else
14968 return (1);
14969 return (ret);
14970}
14971
14972/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014973 * xmlSchemaHasElemContent:
14974 * @node: the node
14975 *
14976 * Scours the content of the given node for element
14977 * nodes.
14978 *
14979 * Returns 1 if an element node is found,
14980 * 0 otherwise.
14981 */
14982static int
14983xmlSchemaHasElemContent(xmlNodePtr node)
14984{
14985 if (node == NULL)
14986 return (0);
14987 node = node->children;
14988 while (node != NULL) {
14989 if (node->type == XML_ELEMENT_NODE)
14990 return (1);
14991 node = node->next;
14992 }
14993 return (0);
14994}
14995/**
14996 * xmlSchemaHasElemOrCharContent:
14997 * @node: the node
14998 *
14999 * Scours the content of the given node for element
15000 * and character nodes.
15001 *
15002 * Returns 1 if an element or character node is found,
15003 * 0 otherwise.
15004 */
15005static int
15006xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15007{
15008 if (node == NULL)
15009 return (0);
15010 node = node->children;
15011 while (node != NULL) {
15012 switch (node->type) {
15013 case XML_ELEMENT_NODE:
15014 /*
15015 * TODO: Ask Daniel if these are all character nodes.
15016 */
15017 case XML_TEXT_NODE:
15018 case XML_CDATA_SECTION_NODE:
15019 /*
15020 * TODO: How XML_ENTITY_NODEs evaluated?
15021 */
15022 case XML_ENTITY_REF_NODE:
15023 case XML_ENTITY_NODE:
15024 return (1);
15025 break;
15026 default:
15027 break;
15028 }
15029 node = node->next;
15030 }
15031 return (0);
15032}
15033
15034
15035/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015036 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015037 * @ctxt: a schema validation context
15038 * @node: the top node.
15039 *
15040 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015041 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015042 *
15043 * Returns 0 if the element is schemas valid, a positive error code
15044 * number otherwise and -1 in case of internal or API error.
15045 */
15046static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015047xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15048 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015049{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015050 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015051 int ret = 0;
15052 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015053 xmlAttrPtr attr;
15054 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015055 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015056
15057 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015058 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15059 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015060 * Note that @elemDecl will be the declaration and never the
15061 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015062 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015063
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015064 if (ctxt == NULL) {
15065 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15066 "Internal error: xmlSchemaValidateElementByDeclaration, "
15067 "bad arguments.\n",
15068 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015069 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015070 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015071
15072 elem = ctxt->node;
15073
15074 /*
15075 * cvc-elt (3.3.4) : 1
15076 */
15077 if (elemDecl == NULL) {
15078 xmlSchemaVCustomErr(ctxt,
15079 XML_SCHEMAV_CVC_ELT_1,
15080 elem, NULL,
15081 "No matching declaration available", NULL);
15082 return (ctxt->err);
15083 }
15084 /*
15085 * cvc-elt (3.3.4) : 2
15086 */
15087 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15088 xmlSchemaVCustomErr(ctxt,
15089 XML_SCHEMAV_CVC_ELT_2,
15090 elem, NULL,
15091 "The element declaration is abstract", NULL);
15092 return (ctxt->err);
15093 }
15094
15095 /*
15096 * cvc-elt (3.3.4) : 3
15097 * Handle 'xsi:nil'.
15098 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015099
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015100 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015101 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015102 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15103 ctxt->node = (xmlNodePtr) attr;
15104 ctxt->cur = attr->children;
15105 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15106 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15107 BAD_CAST attrValue, 1, 1, 1, 1);
15108 ctxt->node = elem;
15109 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15110 if (ret < 0) {
15111 xmlSchemaVCustomErr(ctxt,
15112 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015113 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015114 "Internal error: xmlSchemaValidateElementByDeclaration, "
15115 "validating the attribute 'xsi:nil'", NULL);
15116 if (attrValue != NULL)
15117 xmlFree(attrValue);
15118 return (-1);
15119 }
15120 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015121 /*
15122 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015123 */
15124 xmlSchemaVCustomErr(ctxt,
15125 XML_SCHEMAV_CVC_ELT_3_1,
15126 elem, NULL,
15127 "The element is not 'nillable'", NULL);
15128 } else {
15129 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015130 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015131 ret = 0;
15132 /*
15133 * cvc-elt (3.3.4) : 3.2.1
15134 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015135 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15136 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015137 xmlSchemaVCustomErr(ctxt,
15138 XML_SCHEMAV_CVC_ELT_3_2_1,
15139 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015140 elem, (xmlSchemaTypePtr) elemDecl,
15141 "The 'nilled' element must have no character or "
15142 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015143 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15144 }
15145 /*
15146 * cvc-elt (3.3.4) : 3.2.2
15147 */
15148 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15149 (elemDecl->value != NULL)) {
15150 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15151 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015152 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015153 "There is a fixed value constraint defined for "
15154 "the 'nilled' element", NULL);
15155 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15156 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015157 if (ret == 0)
15158 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015159 }
15160 }
15161 if (attrValue != NULL)
15162 xmlFree(attrValue);
15163 }
15164
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015165
15166 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015167 /*
15168 * cvc-elt (3.3.4) : 4
15169 * Handle 'xsi:type'.
15170 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015171
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015172 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15173 if (attr != NULL) {
15174 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015175
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015176 /*
15177 * TODO: We should report a *warning* that the type was overriden
15178 * by the instance.
15179 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015180
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015181 /*
15182 * cvc-elt (3.3.4) : 4.1
15183 */
15184 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15185 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15186 &nsName, &local);
15187 if (ret < 0) {
15188 xmlSchemaVCustomErr(ctxt,
15189 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015190 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015191 "Internal error: xmlSchemaValidateElementByDeclaration, "
15192 "validating the attribute 'xsi:type'", NULL);;
15193 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015194 FREE_AND_NULL(nsName)
15195 FREE_AND_NULL(local)
15196 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015197 } else if (ret == 1) {
15198 xmlSchemaVSimpleTypeErr(ctxt,
15199 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15200 (xmlNodePtr) attr, attrValue,
15201 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15202 } else if (ret == 2) {
15203 xmlSchemaVCustomErr(ctxt,
15204 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15205 (xmlNodePtr) attr,
15206 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15207 "The QName value '%s' has no "
15208 "corresponding namespace declaration in scope",
15209 attrValue);
15210 } else {
15211 /*
15212 * cvc-elt (3.3.4) : 4.2
15213 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015214 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15215 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015216 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015217
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015218 xmlSchemaVCustomErr(ctxt,
15219 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015220 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015221 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15222 "The value %s does not resolve to a type "
15223 "definition",
15224 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15225 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015226 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015227 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015228 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015229 */
15230 }
15231 }
15232 FREE_AND_NULL(attrValue)
15233 FREE_AND_NULL(nsName)
15234 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015235 }
15236 /* TODO: Change the handling of missing types according to
15237 * the spec.
15238 */
15239 if (actualType == NULL) {
15240 xmlSchemaVComplexTypeErr(ctxt,
15241 XML_SCHEMAV_CVC_TYPE_1,
15242 elem, (xmlSchemaTypePtr) elemDecl,
15243 "The type definition is absent");
15244 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015245 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015246
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015247 /*
15248 * TODO: Since this should be already checked by the content model automaton,
15249 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15250 * has been changed to XML_SCHEMAV_INTERNAL.
15251 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015252 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015253 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015254 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015255 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015256 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015257 "Element %s: missing child %s\n",
15258 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015259 }
15260 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015261 }
15262 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015263 /*
15264 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015265 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015266 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015267 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015268 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015269 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015270 "Element %s: missing child %s found %s\n",
15271 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015272 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015273 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015274 */
15275 if (elemHasContent == -1)
15276 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15277 /*
15278 * cvc-elt (3.3.4) : 5
15279 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015280 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015281 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015282 * cvc-elt (3.3.4) : 5.1
15283 * If the declaration has a {value constraint},
15284 * the item has neither element nor character [children] and
15285 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015286 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015287 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15288 /*
15289 * cvc-elt (3.3.4) : 5.1.1
15290 * If the ·actual type definition· is a ·local type definition·
15291 * then the canonical lexical representation of the {value constraint}
15292 * value must be a valid default for the ·actual type definition· as
15293 * defined in Element Default Valid (Immediate) (§3.3.6).
15294 */
15295 /*
15296 * NOTE: 'local' above means types aquired by xsi:type.
15297 */
15298 ret = 0;
15299 if (actualType != elemDecl->subtypes) {
15300 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15301 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15302 elemDecl->value, NULL);
15303 if (ret < 0) {
15304 xmlSchemaVCustomErr(ctxt,
15305 XML_SCHEMAV_INTERNAL,
15306 elem, actualType,
15307 "Internal error: xmlSchemaValidateElementByDeclaration, "
15308 "validating a default value", NULL);
15309 return (-1);
15310 }
15311 }
15312 /*
15313 * cvc-elt (3.3.4) : 5.1.2
15314 * The element information item with the canonical lexical
15315 * representation of the {value constraint} value used as its
15316 * ·normalized value· must be ·valid· with respect to the
15317 * ·actual type definition· as defined by Element Locally Valid (Type)
15318 * (§3.3.4).
15319 */
15320 /*
15321 * Disable validation of the simple content, since it was already
15322 * done above.
15323 */
15324 if (ret == 0) {
15325 if (actualType != elemDecl->subtypes)
15326 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15327 else
15328 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15329 ctxt->node = elem;
15330 if (ret < 0) {
15331 xmlSchemaVCustomErr(ctxt,
15332 XML_SCHEMAV_INTERNAL,
15333 elem, actualType,
15334 "Internal error: xmlSchemaValidateElementByDeclaration, "
15335 "validating against the type", NULL);
15336 return (-1);
15337 }
15338 /*
15339 * PSVI: Create a text node on the instance element.
15340 */
15341 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15342 xmlNodePtr textChild;
15343
15344 textChild = xmlNewText(elemDecl->value);
15345 if (textChild == NULL) {
15346 xmlSchemaVCustomErr(ctxt,
15347 XML_SCHEMAV_INTERNAL,
15348 elem, actualType,
15349 "Internal error: xmlSchemaValidateElementByDeclaration, "
15350 "could not create a default text node for the instance",
15351 NULL);
15352 } else
15353 xmlAddChild(elem, textChild);
15354 }
15355 }
15356
15357 } else {
15358 /*
15359 * 5.2.1 The element information item must be ·valid· with respect
15360 * to the ·actual type definition· as defined by Element Locally
15361 * Valid (Type) (§3.3.4).
15362 */
15363 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15364 ctxt->node = elem;
15365 if (ret < 0) {
15366 xmlSchemaVCustomErr(ctxt,
15367 XML_SCHEMAV_INTERNAL,
15368 elem, actualType,
15369 "Internal error: xmlSchemaValidateElementByDeclaration, "
15370 "validating a default value", NULL);
15371 return (-1);
15372 }
15373 /*
15374 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15375 * not applied, all of the following must be true:
15376 */
15377
15378 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15379 /*
15380 * 5.2.2.1 The element information item must have no element
15381 * information item [children].
15382 *
15383 * TODO REDUNDANT: If the actual type exists, the above call to
15384 * xmlSchemaValidateElementByType will already check for element
15385 * nodes.
15386 */
15387 if (xmlSchemaHasElemContent(elem)) {
15388 xmlSchemaVCustomErr(ctxt,
15389 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15390 elem, (xmlSchemaTypePtr) elemDecl,
15391 "Elements in the content are not allowed if it is "
15392 "constrained by a fixed value", NULL);
15393 } else {
15394 /*
15395 * 5.2.2.2 The appropriate case among the following must
15396 * be true:
15397 */
15398
15399 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15400 xmlChar *value;
15401 /*
15402 * 5.2.2.2.1 If the {content type} of the ·actual type
15403 * definition· is mixed, then the *initial value* of the
15404 * item must match the canonical lexical representation
15405 * of the {value constraint} value.
15406 *
15407 * ... the *initial value* of an element information
15408 * item is the string composed of, in order, the
15409 * [character code] of each character information item in
15410 * the [children] of that element information item.
15411 */
15412 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15413 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15414 /*
15415 * TODO: Report invalid & expected values as well.
15416 * TODO: Implement the cononical stuff.
15417 */
15418 xmlSchemaVCustomErr(ctxt,
15419 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15420 elem, (xmlSchemaTypePtr) elemDecl,
15421 "The value does not match the cononical "
15422 "lexical representation of the fixed constraint",
15423 NULL);
15424 }
15425 if (value != NULL)
15426 xmlFree(value);
15427 } else if ((actualType->contentType ==
15428 XML_SCHEMA_CONTENT_SIMPLE) ||
15429 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15430 xmlChar *value;
15431
15432 /*
15433 * 5.2.2.2.2 If the {content type} of the ·actual type
15434 * definition· is a simple type definition, then the
15435 * *actual value* of the item must match the canonical
15436 * lexical representation of the {value constraint} value.
15437 */
15438 /*
15439 * TODO: *actual value* is the normalized value, impl. this.
15440 * TODO: Report invalid & expected values as well.
15441 * TODO: Implement the cononical stuff.
15442 *
15443 */
15444 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15445 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15446 xmlSchemaVCustomErr(ctxt,
15447 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15448 elem, (xmlSchemaTypePtr) elemDecl,
15449 "The normalized value does not match the cononical "
15450 "lexical representation of the fixed constraint",
15451 NULL);
15452 }
15453 if (value != NULL)
15454 xmlFree(value);
15455
15456 }
15457 /*
15458 * TODO: What if the content type is not 'mixed' or simple?
15459 */
15460
15461 }
15462
15463 }
15464 }
15465
15466 /*
15467 * TODO: 6 The element information item must be ·valid· with respect to each of
15468 * the {identity-constraint definitions} as per Identity-constraint
15469 * Satisfied (§3.11.4).
15470 */
15471
15472 /*
15473 * TODO: 7 If the element information item is the ·validation root·, it must be
15474 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15475 */
15476
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015477 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015478}
15479
Daniel Veillard4255d502002-04-16 15:50:10 +000015480/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015481 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015482 * @ctxt: a schema validation context
15483 * @node: the top node.
15484 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015485 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15486 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015487 *
15488 * Returns 0 if the element is valid, a positive error code
15489 * number otherwise and -1 in case of an internal error.
15490 */
15491static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015492xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15493 xmlSchemaWildcardPtr wild,
15494 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015495{
15496 const xmlChar *uri;
15497 int ret = 0;
15498 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015499
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015500 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015501 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15502 if (ret == -1) {
15503 xmlSchemaVCustomErr(ctxt,
15504 XML_SCHEMAV_INTERNAL,
15505 ctxt->node, NULL,
15506 "Internal error: xmlSchemaValidateElement, "
15507 "assembling schema by xsi", NULL);
15508 return (-1);
15509 }
15510 /*
15511 * NOTE: We won't react on schema parser errors here.
15512 * TODO: But a warning would be nice.
15513 */
15514 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015515 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15516 xmlSchemaElementPtr decl = NULL;
15517
15518 if (node->ns != NULL)
15519 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15520 node->name, node->ns->href, NULL);
15521 else
15522 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15523 if (decl != NULL) {
15524 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015525 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015526 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015527 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015528 "Internal error: xmlSchemaValidateAnyInternal, "
15529 "validating an element in the context of a wildcard.",
15530 NULL, NULL);
15531 } else if (ret > 0)
15532 return (ret);
15533 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15534 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015535 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015536 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015537 return (ctxt->err);
15538 }
15539 }
15540 if (node->children != NULL) {
15541 child = node->children;
15542 do {
15543 if (child->type == XML_ELEMENT_NODE) {
15544 if (child->ns != NULL)
15545 uri = child->ns->href;
15546 else
15547 uri = NULL;
15548 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015549 /* TODO: error code. */
15550 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015551 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015552 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015553 return (ctxt->err);
15554 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015555 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15556 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015557 if (ret != 0)
15558 return (ret);
15559 }
15560 child = child->next;
15561 } while (child != NULL);
15562 }
15563 return (0);
15564}
15565
15566/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015567 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015568 * @ctxt: a schema validation context
15569 *
15570 * Returns 0 if the element is valid, a positive error code
15571 * number otherwise and -1 in case of an internal or API error.
15572 */
15573static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015574xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15575 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015576{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015577 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15578 (ctxt->node == NULL)) {
15579 xmlSchemaVCustomErr(ctxt,
15580 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15581 "Internal error: xmlSchemaValidateElementByWildcard, "
15582 "bad arguments", NULL);
15583 return (-1);
15584 }
15585 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15586 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015587}
15588
15589/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015590 * xmlSchemaValidateAnyTypeContent:
15591 * @ctxt: a schema validation context
15592 * @node: the current element
15593 *
15594 * This one validates the content of an element of the type
15595 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15596 * thus elements in the subtree will be validated, if a corresponding
15597 * declaration in the schema exists.
15598 *
15599 * Returns 0 if the element and its subtree is valid, a positive error code
15600 * otherwise and -1 in case of an internal or API error.
15601 */
15602static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015603xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15604 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015605{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015606 xmlSchemaTypePtr oldtype;
15607 xmlNodePtr top, cur;
15608 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015609 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015610
15611 if ((type == NULL) || (ctxt->node == NULL))
15612 return (-1);
15613
15614 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015615 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015616
15617 oldtype = ctxt->type;
15618 top = ctxt->node;
15619 /*
15620 * STREAM: Child nodes are processed.
15621 */
15622 cur = ctxt->node->children;
15623 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015624 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015625 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015626 /*
15627 * The process contents of the wildcard is "lax", thus
15628 * we need to validate the element if a declaration
15629 * exists.
15630 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015631 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015632 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015633 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015634 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015635 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015636 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015637 ctxt->node = cur;
15638 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15639 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015640 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015641 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015642 "Internal error: xmlSchemaValidateAnyTypeContent, "
15643 "validating an element in the context of a wildcard.",
15644 NULL, NULL);
15645 return (ret);
15646 } else if (ret > 0)
15647 return (ret);
15648 skipContent = 1;
15649 }
15650 }
15651 /*
15652 * Browse the full subtree, deep first.
15653 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015654 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015655 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015656 cur = cur->children;
15657 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015658 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015659 cur = cur->next;
15660 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015661 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015662 while (cur != top) {
15663 if (cur->parent != NULL)
15664 cur = cur->parent;
15665 if ((cur != top) && (cur->next != NULL)) {
15666 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015667 break;
15668 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015669 if (cur->parent == NULL) {
15670 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015671 break;
15672 }
15673 }
15674 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015675 if (cur == top)
15676 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015677 } else
15678 break;
15679 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015680 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015681 return (0);
15682}
15683
15684/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015685 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015686 * @ctxt: a schema validation context
15687 * @node: the top node.
15688 *
15689 * Validate the content of an element expected to be a complex type type
15690 * xmlschema-1.html#cvc-complex-type
15691 * Validation Rule: Element Locally Valid (Complex Type)
15692 *
15693 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015694 * number otherwise and -1 in case of internal or API error.
15695 * Note on reported errors: Although it might be nice to report
15696 * the name of the simple/complex type, used to validate the content
15697 * of a node, it is quite unnecessary: for global defined types
15698 * the local name of the element is equal to the NCName of the type,
15699 * for local defined types it makes no sense to output the internal
15700 * computed name of the type. TODO: Instead, one should attach the
15701 * struct of the type involved to the error handler - this allows
15702 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015703 */
15704static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015705xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015706 xmlSchemaTypePtr type,
15707 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015708{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015709 xmlSchemaTypePtr oldtype;
15710 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015711 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015712 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015713 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015715 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15716 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015717
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015718 oldtype = ctxt->type;
15719 ctxt->type = type;
15720 elem = ctxt->node;
15721
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015722 /*
15723 * Verify the attributes
15724 */
15725 /*
15726 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015727 */
15728 /* NOTE: removed, since a check for abstract is
15729 * done in the cvc-type constraint.
15730 *
15731 *
15732 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15733 * xmlSchemaVComplexTypeErr(ctxt,
15734 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15735 * elem, type,
15736 * "The type definition is abstract");
15737 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15738 *}
15739 */
15740
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015741 attrs = ctxt->attr;
15742 attrTop = ctxt->attrTop;
15743 /*
15744 * STREAM: Attribute nodes are processed.
15745 */
15746 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15747 xmlSchemaValidateAttributes(ctxt, elem, type);
15748 if (ctxt->attr != NULL)
15749 xmlSchemaFreeAttributeStates(ctxt->attr);
15750 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015751 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015752
15753 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015754 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015755 * model was defined. Somehow ->contModel is always not NULL
15756 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015757 * TODO: Check if the obove still occurs.
15758 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015759 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015760 case XML_SCHEMA_CONTENT_EMPTY: {
15761 /*
15762 * 1 If the {content type} is empty, then the element information
15763 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015764 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015765 /*
15766 * TODO: Is the entity stuff correct?
15767 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015768 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015769 xmlSchemaVComplexTypeErr(ctxt,
15770 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015771 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015772 "Character or element content is not allowed, "
15773 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015774 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015775 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015776 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015777 case XML_SCHEMA_CONTENT_MIXED:
15778 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015779 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015780 /*
15781 * The type has 'anyType' as its base and no content model
15782 * is defined -> use 'anyType' as the type to validate
15783 * against.
15784 */
15785 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15786 /* TODO: Handle -1. */
15787 break;
15788 }
15789 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015790 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015791 {
15792 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015793
15794 /*
15795 * Content model check initialization.
15796 */
15797 if (type->contModel != NULL) {
15798 oldregexp = ctxt->regexp;
15799 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15800 (xmlRegExecCallbacks)
15801 xmlSchemaValidateCallback, ctxt);
15802#ifdef DEBUG_AUTOMATA
15803 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15804#endif
15805 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015806 /*
15807 * STREAM: Children are processed.
15808 */
15809 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015810 while (child != NULL) {
15811 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015812 if (child->ns != NULL)
15813 nsUri = child->ns->href;
15814 else
15815 nsUri = NULL;
15816 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015817 child->name, nsUri, child);
15818 /*
15819 * URGENT TODO: Could we anchor an error report
15820 * here to notify of invalid elements?
15821 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015822#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015823 if (ret < 0)
15824 xmlGenericError(xmlGenericErrorContext,
15825 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015826 else
15827 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015828 " --> %s\n", child->name);
15829#endif
15830 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15831 /*
15832 * TODO: Ask Daniel if this are all character nodes.
15833 */
15834 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15835 (child->type == XML_ENTITY_NODE) ||
15836 (child->type == XML_ENTITY_REF_NODE) ||
15837 (child->type == XML_CDATA_SECTION_NODE))) {
15838 /*
15839 * 2.3 If the {content type} is element-only, then the
15840 * element information item has no character information
15841 * item [children] other than those whose [character
15842 * code] is defined as a white space in [XML 1.0 (Second
15843 * Edition)].
15844 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015845 xmlSchemaVComplexTypeErr(ctxt,
15846 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015847 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015848 "Character content is not allowed, "
15849 "because the content type is element-only");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015850 break;
15851 }
15852 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015853 }
15854 /*
15855 * Content model check finalization.
15856 */
15857 if (type->contModel != NULL) {
15858 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
15859#ifdef DEBUG_AUTOMATA
15860 xmlGenericError(xmlGenericErrorContext,
15861 "====> %s : %d\n", elem->name, ret);
15862#endif
15863 if (ret == 0) {
15864 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15865 elem, type, "The element content is not valid", NULL);
15866 } else if (ret < 0) {
15867 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
15868 elem, type, "The element content is not valid", NULL);
15869#ifdef DEBUG_CONTENT
15870 } else {
15871 xmlGenericError(xmlGenericErrorContext,
15872 "Element %s content check succeeded\n",
15873 elem->name);
15874
15875#endif
15876 }
15877 xmlRegFreeExecCtxt(ctxt->regexp);
15878 ctxt->regexp = oldregexp;
15879 }
15880 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015881 break;
15882 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015883 case XML_SCHEMA_CONTENT_BASIC:
15884 /*
15885 * If the simple content was already validated
15886 * (e.g. a default value), the content need not
15887 * to be validated again.
15888 */
15889 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015890 xmlChar *value = NULL;
15891 /*
15892 * We hit a complexType with a simpleContent resolving
15893 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015894 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015895 /*
15896 * 2.2 If the {content type} is a simple type definition,
15897 * then the element information item has no element
15898 * information item [children], and the ·normalized value·
15899 * of the element information item is ·valid· with respect
15900 * to that simple type definition as defined by String
15901 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015902 */
15903 /*
15904 * STREAM: Children are processed.
15905 */
15906 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015907 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015908 /*
15909 * TODO: Could the entity stuff produce elements
15910 * as well?
15911 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015912 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015913 xmlSchemaVComplexTypeErr(ctxt,
15914 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015915 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015916 "Element content is not allowed, because "
15917 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015918 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15919 break;
15920 }
15921 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015922 }
15923 ctxt->node = elem;
15924 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015925 if (ret == 0) {
15926 /*
15927 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015928 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015929 /*
15930 * STREAM: Children are processed.
15931 */
15932 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015933 value = NULL;
15934 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015935 value = xmlNodeGetContent(elem);
15936 /*
15937 * URGENT TODO: Should facets for the simple type validation be
15938 * disabled, if the derivation of facets for complex types
15939 * is implemented?
15940 */
15941 /*
15942 * NOTE: This call won't check the correct types of the
15943 * content nodes, since this should be done here.
15944 */
15945 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015946 if (ret > 0) {
15947 /*
15948 * NOTE: Although an error will be reported by
15949 * xmlSchemaValidateSimpleTypeValue, the spec wants
15950 * a specific complex type error to be reported
15951 * additionally.
15952 */
15953 xmlSchemaVComplexTypeErr(ctxt,
15954 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015955 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015956 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015957 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15958 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015959 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015960 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015961 "Element '%s': Error while validating character "
15962 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015963 elem->name, type->name);
15964 if (value != NULL)
15965 xmlFree(value);
15966 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015967 return (-1);
15968 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015969 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015970 if (ret == 0) {
15971 /*
15972 * Apply facets of the complexType. Be sure to pass the
15973 * built-in type to xmlSchemaValidateFacetsInternal.
15974 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015975 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000015976 * are used, or if the facets, defined by this complex type,
15977 * are to be used only. This here applies both facet sets.
15978 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015979
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015980 ret = xmlSchemaValidateFacetsInternal(ctxt,
15981 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015983 xmlSchemaVComplexTypeErr(ctxt,
15984 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015985 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015986 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015987 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15988 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015989 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015990 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015991 "Element '%s': Error while validating character "
15992 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000015993 "apply facets.\n",
15994 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015995 if (value != NULL)
15996 xmlFree(value);
15997 ctxt->type = oldtype;
15998 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015999 }
16000 }
16001 if (value != NULL)
16002 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016003
Daniel Veillard01fa6152004-06-29 17:04:39 +000016004 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016005 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016006 default:
16007 TODO xmlGenericError(xmlGenericErrorContext,
16008 "unimplemented content type %d\n",
16009 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016010 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016011 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016012 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016013}
16014
16015/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016016 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016017 * @ctxt: a schema validation context
16018 * @elem: an element
16019 * @type: the list of type declarations
16020 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016021 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016022 *
16023 * Returns 0 if the element is schemas valid, a positive error code
16024 * number otherwise and -1 in case of internal or API error.
16025 */
16026static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016027xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016028 xmlSchemaTypePtr type,
16029 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016030{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016031 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016032
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016033
16034 if ((ctxt == NULL) || (type == NULL)) {
16035 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16036 "Internal error: xmlSchemaValidateElementByType, "
16037 "bad arguments", NULL);
16038 return (-1);
16039 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016040 /*
16041 * This one is called by "xmlSchemaValidateElementByDeclaration".
16042 * It will forward to the proper validation
16043 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016044 */
16045 if (type == NULL) {
16046 xmlSchemaVComplexTypeErr(ctxt,
16047 XML_SCHEMAV_CVC_TYPE_1,
16048 ctxt->node, NULL,
16049 "The type definition is absent");
16050 return (XML_SCHEMAV_CVC_TYPE_1);
16051 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016052
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016053 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
16054 xmlSchemaVComplexTypeErr(ctxt,
16055 XML_SCHEMAV_CVC_TYPE_2,
16056 ctxt->node, type,
16057 "The type definition is abstract");
16058 return (XML_SCHEMAV_CVC_TYPE_2);
16059 }
16060
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016061 switch (type->type) {
16062 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016063 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16064 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016065 break;
16066 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016067 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16068 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016069 break;
16070 case XML_SCHEMA_TYPE_BASIC:
16071 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16072 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16073 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016074 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16075 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016076 break;
16077 default:
16078 ret = -1;
16079 break;
16080 }
16081 if (ret == -1)
16082 return (-1);
16083 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016084 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016085}
16086
16087
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016088static int
16089xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16090 xmlSchemaAttributePtr decl,
16091 xmlSchemaAttrStatePtr state,
16092 xmlAttrPtr attr)
16093{
16094 xmlChar *value;
16095 const xmlChar *defValue;
16096 xmlSchemaValPtr defVal;
16097 int fixed;
16098 int ret;
16099
16100 if (decl->subtypes == NULL) {
16101 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16102 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16103 }
16104 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16105 ctxt->node = (xmlNodePtr) attr;
16106 ctxt->cur = attr->children;
16107 /*
16108 * NOTE: This call also checks the content nodes for correct type.
16109 */
16110 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16111 value, 1, 1, 1, 1);
16112
16113 /*
16114 * Handle 'fixed' attributes.
16115 */
16116 if (ret > 0) {
16117 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16118 /*
16119 * NOTE: Fixed value constraints will be not
16120 * applied if the value was invalid, because:
16121 * 1. The validation process does not return a precomputed
16122 * value.
16123 * 2. An invalid value implies a violation of a fixed
16124 * value constraint.
16125 */
16126 } else if (ret == 0) {
16127 state->state = XML_SCHEMAS_ATTR_CHECKED;
16128 if (xmlSchemaGetEffectiveValueConstraint(decl,
16129 &fixed, &defValue, &defVal) && (fixed == 1)) {
16130 /*
16131 * cvc-au : Attribute Locally Valid (Use)
16132 * For an attribute information item to be·valid·
16133 * with respect to an attribute use its ·normalized
16134 * value· must match the canonical lexical representation
16135 * of the attribute use's {value constraint} value, if it
16136 * is present and fixed.
16137 */
16138 /*
16139 * NOTE: the validation context holds in ctxt->value the
16140 * precomputed value of the attribute; well for some types,
16141 * fallback to string comparison if no computed value
16142 * exists.
16143 */
16144 if (((ctxt->value != NULL) &&
16145 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16146 ((ctxt->value == NULL) &&
16147 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16148 state->state =
16149 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16150 }
16151 }
16152 }
16153 if (value != NULL) {
16154 xmlFree(value);
16155 }
16156 return (ret);
16157}
16158
Daniel Veillard4255d502002-04-16 15:50:10 +000016159/**
16160 * xmlSchemaValidateAttributes:
16161 * @ctxt: a schema validation context
16162 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016163 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016164 *
16165 * Validate the attributes of an element.
16166 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016167 * 1. Existent, invalid attributes are reported in the form
16168 * "prefix:localName".
16169 * Reason: readability - it is easier to find the actual XML
16170 * representation of the attributes QName.
16171 * 2. Missing attributes are reported in the form
16172 * {"URI", "localName"}.
16173 * This is necessary, since the the prefix need not to be declared
16174 * at all, and thus is not computable.
16175 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016176 * Returns 0 if the element is schemas valid, a positive error code
16177 * number otherwise and -1 in case of internal or API error.
16178 */
16179static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016180xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016181{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016182 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016183 int ret;
16184 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016185 const xmlChar *defValue;
16186 xmlSchemaValPtr defVal;
16187 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016188 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016189 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016190 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016191 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016192 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016193 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016194#ifdef DEBUG_ATTR_VALIDATION
16195 int redundant = 0;
16196#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016197
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016198
Daniel Veillardc0826a72004-08-10 14:17:33 +000016199 /*
16200 * Allow all attributes if the type is anyType.
16201 */
16202 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16203 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016204
16205 oldnode = ctxt->node;
16206 if (type != NULL)
16207 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016208 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016209 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016210 attrDecl = attrUse->attr;
16211#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016212 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016213 printf("attr use - use: %d\n", attrDecl->occurs);
16214#endif
16215 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16216
16217 if (curState->decl == attrUse->attr) {
16218#ifdef DEBUG_ATTR_VALIDATION
16219 redundant = 1;
16220#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016221 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016222 attr = curState->attr;
16223#ifdef DEBUG_ATTR_VALIDATION
16224 printf("attr - name: %s\n", attr->name);
16225 if (attr->ns != NULL)
16226 printf("attr - ns: %s\n", attr->ns->href);
16227 else
16228 printf("attr - ns: none\n");
16229#endif
16230 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016231 if (attr == NULL)
16232 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016233 if (attrDecl->ref != NULL) {
16234 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016235 continue;
16236 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016237 if ((attrDecl->refNs == NULL) ||
16238 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016239 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016240 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016241 continue;
16242 }
16243 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016244 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016245 continue;
16246 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016247 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016248 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016249 if (attr->ns == NULL) {
16250 /*
William M. Bracke7091952004-05-11 15:09:58 +000016251 * accept an unqualified attribute only if the target
16252 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016253 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016254 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016255 /*
16256 * This check was removed, since the target namespace
16257 * was evaluated during parsing and already took
16258 * "attributeFormDefault" into account.
16259 */
16260 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016261 continue;
16262 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016263 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016264 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016265 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016266 attr->ns->href))
16267 continue;
16268 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016269 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016270#ifdef DEBUG_ATTR_VALIDATION
16271 printf("found\n");
16272#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016273 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016274 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016275 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016276 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016277 if (!found) {
16278 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16279 xmlSchemaAttrStatePtr tmp;
16280
Daniel Veillard3646d642004-06-02 19:19:14 +000016281#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016282 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016283#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016284 /*
16285 * Add a new dummy attribute state.
16286 */
16287 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16288 if (tmp == NULL) {
16289 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16290 ctxt->node = oldnode;
16291 return (-1);
16292 }
16293 tmp->attr = NULL;
16294 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16295 tmp->decl = attrDecl;
16296 tmp->next = NULL;
16297
16298 if (reqAttrStates == NULL) {
16299 reqAttrStates = tmp;
16300 reqAttrStatesTop = tmp;
16301 } else {
16302 reqAttrStatesTop->next = tmp;
16303 reqAttrStatesTop = tmp;
16304 }
16305 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16306 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16307 &fixed, &defValue, &defVal))) {
16308 xmlSchemaAttrStatePtr tmp;
16309 /*
16310 * Handle non existent default/fixed attributes.
16311 */
16312 tmp = (xmlSchemaAttrStatePtr)
16313 xmlMalloc(sizeof(xmlSchemaAttrState));
16314 if (tmp == NULL) {
16315 xmlSchemaVErrMemory(ctxt,
16316 "registering schema specified attributes", NULL);
16317 ctxt->node = oldnode;
16318 return (-1);
16319 }
16320 tmp->attr = NULL;
16321 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16322 tmp->decl = attrDecl;
16323 tmp->value = defValue;
16324 tmp->next = NULL;
16325
16326 if (defAttrStates == NULL) {
16327 defAttrStates = tmp;
16328 defAttrStates = tmp;
16329 } else {
16330 defAttrStates->next = tmp;
16331 defAttrStatesTop = tmp;
16332 }
16333 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016334 }
16335 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016336 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016337 /*
16338 * Add required attributes to the attribute states of the context.
16339 */
16340 if (reqAttrStates != NULL) {
16341 if (ctxt->attr == NULL) {
16342 ctxt->attr = reqAttrStates;
16343 } else {
16344 ctxt->attrTop->next = reqAttrStates;
16345 }
16346 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016347 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016348 /*
16349 * Process wildcards.
16350 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016351
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016352 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016353#ifdef DEBUG_ATTR_VALIDATION
16354 xmlSchemaWildcardNsPtr ns;
16355 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016356 if (type->attributeWildcard->processContents ==
16357 XML_SCHEMAS_ANY_LAX)
16358 printf("processContents: lax\n");
16359 else if (type->attributeWildcard->processContents ==
16360 XML_SCHEMAS_ANY_STRICT)
16361 printf("processContents: strict\n");
16362 else
16363 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016364 if (type->attributeWildcard->any)
16365 printf("type: any\n");
16366 else if (type->attributeWildcard->negNsSet != NULL) {
16367 printf("type: negated\n");
16368 if (type->attributeWildcard->negNsSet->value == NULL)
16369 printf("ns: (absent)\n");
16370 else
16371 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16372 } else if (type->attributeWildcard->nsSet != NULL) {
16373 printf("type: set\n");
16374 ns = type->attributeWildcard->nsSet;
16375 while (ns != NULL) {
16376 if (ns->value == NULL)
16377 printf("ns: (absent)\n");
16378 else
16379 printf("ns: %s\n", ns->value);
16380 ns = ns->next;
16381 }
16382 } else
16383 printf("empty\n");
16384
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016385
16386#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016387 curState = ctxt->attr;
16388 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016389 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16390 if (curState->attr->ns != NULL)
16391 nsURI = curState->attr->ns->href;
16392 else
16393 nsURI = NULL;
16394 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16395 nsURI)) {
16396 /*
16397 * Handle processContents.
16398 */
16399 if ((type->attributeWildcard->processContents ==
16400 XML_SCHEMAS_ANY_LAX) ||
16401 (type->attributeWildcard->processContents ==
16402 XML_SCHEMAS_ANY_STRICT)) {
16403
16404 attr = curState->attr;
16405 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016406 attr->name, nsURI);
16407 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016408 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016409 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016410 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016411 } else if (type->attributeWildcard->processContents ==
16412 XML_SCHEMAS_ANY_LAX) {
16413 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16414 }
16415 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016416 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016417 }
16418 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016419 curState = curState->next;
16420 }
16421 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016422
Daniel Veillardc0826a72004-08-10 14:17:33 +000016423 /*
16424 * Report missing and illegal attributes.
16425 */
16426 if (ctxt->attr != NULL) {
16427 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016428 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016429 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16430 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016431 if (curState->decl != NULL) {
16432 if (curState->decl->ref != NULL)
16433 attrDecl = curState->decl->refDecl;
16434 else
16435 attrDecl = curState->decl;
16436 } else
16437 attrDecl = NULL;
16438 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16439 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16440 } else if (curState->state ==
16441 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16442 xmlSchemaVCustomErr(ctxt,
16443 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16444 (xmlNodePtr) attr,
16445 (xmlSchemaTypePtr) attrDecl,
16446 "The type definition is absent",
16447 NULL);
16448 } else if (curState->state ==
16449 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16450 xmlSchemaVCustomErr(ctxt,
16451 XML_SCHEMAV_CVC_AU,
16452 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16453 "The value does not match the fixed value "
16454 "constraint", NULL);
16455 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016456 /* TODO: "prohibited" won't ever be touched here!.
16457 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16458 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016459 /*
16460 * TODO: One might report different error messages
16461 * for the following errors.
16462 */
16463 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016464 xmlSchemaVIllegalAttrErr(ctxt,
16465 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16466 } else {
16467 xmlSchemaVIllegalAttrErr(ctxt,
16468 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16469 }
16470 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016471 }
16472 curState = curState->next;
16473 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016474 }
16475
16476 /*
16477 * Add missing default/fixed attributes.
16478 */
16479 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16480 curState = defAttrStates;
16481 while (curState != NULL) {
16482 attrDecl = curState->decl;
16483 if (attrDecl->ref != NULL)
16484 attrDecl = attrDecl->refDecl;
16485 /*
16486 * PSVI: Add a new attribute node to the current element.
16487 */
16488 if (attrDecl->targetNamespace == NULL) {
16489 xmlNewProp(elem, attrDecl->name, curState->value);
16490 } else {
16491 xmlNsPtr ns;
16492
16493 ns = xmlSearchNsByHref(elem->doc, elem,
16494 attrDecl->targetNamespace);
16495 if (ns == NULL) {
16496 xmlChar prefix[12];
16497 int counter = 1;
16498
16499 attr = curState->attr;
16500 /*
16501 * Create a namespace declaration on the validation
16502 * root node if no namespace declaration is in scope.
16503 */
16504 snprintf((char *) prefix, sizeof(prefix), "p");
16505 /*
16506 * This is somehow not performant, since the ancestor
16507 * axis beyond @elem will be searched as well.
16508 */
16509 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16510 while (ns != NULL) {
16511 if (counter > 1000) {
16512 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16513 XML_SCHEMAV_INTERNAL,
16514 "Internal error: xmlSchemaValidateAttributes, "
16515 "could not compute a ns prefix for "
16516 "default/fixed attribute '%s'.\n",
16517 attrDecl->name, NULL);
16518
16519 break;
16520 }
16521 snprintf((char *) prefix,
16522 sizeof(prefix), "p%d", counter++);
16523 ns = xmlSearchNs(elem->doc, elem,
16524 BAD_CAST prefix);
16525 }
16526 if (ns == NULL) {
16527 ns = xmlNewNs(ctxt->validationRoot,
16528 attrDecl->targetNamespace, BAD_CAST prefix);
16529 xmlNewNsProp(elem, ns, attrDecl->name,
16530 curState->value);
16531 }
16532 } else {
16533 xmlNewNsProp(elem, ns, attrDecl->name,
16534 curState->value);
16535 }
16536 }
16537 curState = curState->next;
16538 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016539 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016540 if (defAttrStates != NULL)
16541 xmlSchemaFreeAttributeStates(defAttrStates);
16542
Daniel Veillard3646d642004-06-02 19:19:14 +000016543#ifdef DEBUG_ATTR_VALIDATION
16544 if (redundant)
16545 xmlGenericError(xmlGenericErrorContext,
16546 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16547 type->name);
16548#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016549 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016550 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016551}
16552
16553/**
16554 * xmlSchemaValidateElement:
16555 * @ctxt: a schema validation context
16556 * @elem: an element
16557 *
16558 * Validate an element in a tree
16559 *
16560 * Returns 0 if the element is schemas valid, a positive error code
16561 * number otherwise and -1 in case of internal or API error.
16562 */
16563static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016564xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016565{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016566 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016567 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016568
Daniel Veillardc0826a72004-08-10 14:17:33 +000016569 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016570 * This one is called by xmlSchemaValidateDocument and
16571 * xmlSchemaValidateOneElement.
16572 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016573 if (ctxt->schema == NULL) {
16574 /*
16575 * No schema was specified at time of creation of the validation
16576 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16577 * of the instance to build a schema.
16578 */
16579 if (ctxt->pctxt == NULL)
16580 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16581 if (ctxt->pctxt == NULL)
16582 return (-1);
16583 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16584 if (ctxt->schema == NULL)
16585 return (-1);
16586 /* TODO: assign user data. */
16587 ctxt->pctxt->error = ctxt->error;
16588 ctxt->pctxt->warning = ctxt->warning;
16589 ctxt->xsiAssemble = 1;
16590 } else
16591 ctxt->xsiAssemble = 0;
16592 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16593 * ctxt->xsiAssemble = 1;
16594 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016595 /*
16596 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016597 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016598 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016599 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16600 if (ret == -1) {
16601 xmlSchemaVCustomErr(ctxt,
16602 XML_SCHEMAV_INTERNAL,
16603 ctxt->node, NULL,
16604 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016605 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016606 }
16607 /*
16608 * NOTE: We won't react on schema parser errors here.
16609 * TODO: But a warning would be nice.
16610 */
16611 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016612 if (ret != -1) {
16613 if (ctxt->node->ns != NULL)
16614 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16615 ctxt->node->ns->href);
16616 else
16617 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16618
16619 if (elemDecl == NULL) {
16620 xmlSchemaVCustomErr(ctxt,
16621 XML_SCHEMAV_CVC_ELT_1,
16622 ctxt->node, NULL,
16623 "No matching global declaration available", NULL);
16624 ret = XML_SCHEMAV_CVC_ELT_1;
16625 } else {
16626 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16627 if (ret < 0) {
16628 xmlSchemaVCustomErr(ctxt,
16629 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16630 "Internal error: xmlSchemaValidateElement, "
16631 "calling validation by declaration", NULL);
16632 }
16633 }
16634 }
16635 /* ctxt->xsiAssemble = 0; */
16636 if (ctxt->xsiAssemble) {
16637 if (ctxt->schema != NULL) {
16638 xmlSchemaFree(ctxt->schema);
16639 ctxt->schema = NULL;
16640 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016641 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016642 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016643}
16644
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016645
Daniel Veillard4255d502002-04-16 15:50:10 +000016646/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016647 * xmlSchemaValidateOneElement:
16648 * @ctxt: a schema validation context
16649 * @elem: an element node
16650 *
16651 * Validate a branch of a tree, starting with the given @elem.
16652 *
16653 * Returns 0 if the element and its subtree is valid, a positive error
16654 * code number otherwise and -1 in case of an internal or API error.
16655 */
16656int
16657xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16658{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016659 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016660 return (-1);
16661
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016662 if (ctxt->schema == NULL) {
16663 xmlSchemaVErr(ctxt, NULL,
16664 XML_SCHEMAV_INTERNAL,
16665 "API error: xmlSchemaValidateOneElement, "
16666 "no schema specified.\n", NULL, NULL);
16667 return (-1);
16668 }
16669
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016670 ctxt->doc = elem->doc;
16671 ctxt->err = 0;
16672 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016673 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016674 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016675 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016676}
16677
16678/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016679 * xmlSchemaValidateDocument:
16680 * @ctxt: a schema validation context
16681 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016682 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016683 *
16684 * Validate a document tree in memory.
16685 *
16686 * Returns 0 if the document is schemas valid, a positive error code
16687 * number otherwise and -1 in case of internal or API error.
16688 */
16689static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016690xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16691{
Daniel Veillard4255d502002-04-16 15:50:10 +000016692 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016693
Daniel Veillard4255d502002-04-16 15:50:10 +000016694 root = xmlDocGetRootElement(doc);
16695 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016696 xmlSchemaVCustomErr(ctxt,
16697 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16698 (xmlNodePtr) doc, NULL,
16699 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016700 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016701 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016702 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016703 /*
16704 * Okay, start the recursive validation
16705 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016706 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016707 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016708 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016709
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016710 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016711}
16712
16713/************************************************************************
16714 * *
16715 * SAX Validation code *
16716 * *
16717 ************************************************************************/
16718
16719/************************************************************************
16720 * *
16721 * Validation interfaces *
16722 * *
16723 ************************************************************************/
16724
16725/**
16726 * xmlSchemaNewValidCtxt:
16727 * @schema: a precompiled XML Schemas
16728 *
16729 * Create an XML Schemas validation context based on the given schema
16730 *
16731 * Returns the validation context or NULL in case of error
16732 */
16733xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016734xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16735{
Daniel Veillard4255d502002-04-16 15:50:10 +000016736 xmlSchemaValidCtxtPtr ret;
16737
16738 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16739 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016740 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016741 return (NULL);
16742 }
16743 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016744 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016745 ret->attrTop = NULL;
16746 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016747 return (ret);
16748}
16749
16750/**
16751 * xmlSchemaFreeValidCtxt:
16752 * @ctxt: the schema validation context
16753 *
16754 * Free the resources associated to the schema validation context
16755 */
16756void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016757xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16758{
Daniel Veillard4255d502002-04-16 15:50:10 +000016759 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016760 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016761 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016762 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016763 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016764 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016765 if (ctxt->pctxt != NULL) {
16766 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16767 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016768 xmlFree(ctxt);
16769}
16770
16771/**
16772 * xmlSchemaSetValidErrors:
16773 * @ctxt: a schema validation context
16774 * @err: the error function
16775 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016776 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016777 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016778 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016779 */
16780void
16781xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016782 xmlSchemaValidityErrorFunc err,
16783 xmlSchemaValidityWarningFunc warn, void *ctx)
16784{
Daniel Veillard4255d502002-04-16 15:50:10 +000016785 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016786 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016787 ctxt->error = err;
16788 ctxt->warning = warn;
16789 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016790 if (ctxt->pctxt != NULL)
16791 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016792}
16793
16794/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016795 * xmlSchemaGetValidErrors:
16796 * @ctxt: a XML-Schema validation context
16797 * @err: the error function result
16798 * @warn: the warning function result
16799 * @ctx: the functions context result
16800 *
16801 * Get the error and warning callback informations
16802 *
16803 * Returns -1 in case of error and 0 otherwise
16804 */
16805int
16806xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16807 xmlSchemaValidityErrorFunc * err,
16808 xmlSchemaValidityWarningFunc * warn, void **ctx)
16809{
16810 if (ctxt == NULL)
16811 return (-1);
16812 if (err != NULL)
16813 *err = ctxt->error;
16814 if (warn != NULL)
16815 *warn = ctxt->warning;
16816 if (ctx != NULL)
16817 *ctx = ctxt->userData;
16818 return (0);
16819}
16820
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016821
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016822/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016823 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016824 * @ctxt: a schema validation context
16825 * @options: a combination of xmlSchemaValidOption
16826 *
16827 * Sets the options to be used during the validation.
16828 *
16829 * Returns 0 in case of success, -1 in case of an
16830 * API error.
16831 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016832int
16833xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16834 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016835
16836{
16837 int i;
16838
16839 if (ctxt == NULL)
16840 return (-1);
16841 /*
16842 * WARNING: Change the start value if adding to the
16843 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016844 * TODO: Is there an other, more easy to maintain,
16845 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016846 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016847 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016848 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016849 xmlSchemaVErr(ctxt, NULL,
16850 XML_SCHEMAV_INTERNAL,
16851 "Internal error: xmlSchemaSetValidOptions, "
16852 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016853 return (-1);
16854 }
16855 }
16856 ctxt->options = options;
16857 return (0);
16858}
16859
16860/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016861 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016862 * @ctxt: a schema validation context
16863 *
16864 * Returns the option combination of the validation context.
16865 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016866int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016867xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16868
16869{
16870 if (ctxt == NULL)
16871 return (-1);
16872 else
16873 return (ctxt->options);
16874}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016875
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016876
Daniel Veillard259f0df2004-08-18 09:13:18 +000016877/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016878 * xmlSchemaValidateDoc:
16879 * @ctxt: a schema validation context
16880 * @doc: a parsed document tree
16881 *
16882 * Validate a document tree in memory.
16883 *
16884 * Returns 0 if the document is schemas valid, a positive error code
16885 * number otherwise and -1 in case of internal or API error.
16886 */
16887int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016888xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16889{
Daniel Veillard4255d502002-04-16 15:50:10 +000016890 int ret;
16891
16892 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016893 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016894
16895 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016896 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016897 ctxt->nberrors = 0;
16898
16899 /*
16900 if (ctxt->schema == NULL) {
16901 xmlSchemaVErr(ctxt, NULL,
16902 XML_SCHEMAV_INTERNAL,
16903 "API error: xmlSchemaValidateDoc, "
16904 "no schema specified and assembling of schemata "
16905 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16906 "is not enabled.\n", NULL, NULL);
16907 return (-1);
16908 }
16909 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016910 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016911 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016912}
16913
16914/**
16915 * xmlSchemaValidateStream:
16916 * @ctxt: a schema validation context
16917 * @input: the input to use for reading the data
16918 * @enc: an optional encoding information
16919 * @sax: a SAX handler for the resulting events
16920 * @user_data: the context to provide to the SAX handler.
16921 *
16922 * Validate a document tree in memory.
16923 *
16924 * Returns 0 if the document is schemas valid, a positive error code
16925 * number otherwise and -1 in case of internal or API error.
16926 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016927int
Daniel Veillard4255d502002-04-16 15:50:10 +000016928xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016929 xmlParserInputBufferPtr input, xmlCharEncoding enc,
16930 xmlSAXHandlerPtr sax, void *user_data)
16931{
Daniel Veillard4255d502002-04-16 15:50:10 +000016932 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016933 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016934 ctxt->input = input;
16935 ctxt->enc = enc;
16936 ctxt->sax = sax;
16937 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016938 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000016939}
16940
16941#endif /* LIBXML_SCHEMAS_ENABLED */