blob: 60e2b319cba35876b1db48b13613ac1bd7882823 [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 *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000079 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000080static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000081 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000082
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);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000767 /* Local types will get to name
768 *buf = xmlStrcat(*buf, BAD_CAST " ");
769 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000770 }
771 } else if (item->type == XML_SCHEMA_TYPE_COMPLEX) {
772 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
773 *buf = xmlStrdup(xmlSchemaElemDesCT);
774 *buf = xmlStrcat(*buf, BAD_CAST " '");
775 *buf = xmlStrcat(*buf, item->name);
776 *buf = xmlStrcat(*buf, BAD_CAST "'");
777 } else {
778 *buf = xmlStrdup(xmlSchemaElemDesCT);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000779 /* Local types will get to name
780 *buf = xmlStrcat(*buf, BAD_CAST " ");
781 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000782 }
783 } else if (item->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
784 xmlSchemaAttributePtr attr;
785
786 attr = (xmlSchemaAttributePtr) item;
787 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
788 (attr->ref == NULL)) {
789 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
790 *buf = xmlStrcat(*buf, BAD_CAST " '");
791 *buf = xmlStrcat(*buf, attr->name);
792 *buf = xmlStrcat(*buf, BAD_CAST "'");
793 } else {
794 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
795 *buf = xmlStrcat(*buf, BAD_CAST " '");
796 *buf = xmlStrcat(*buf, attr->refPrefix);
797 *buf = xmlStrcat(*buf, BAD_CAST ":");
798 *buf = xmlStrcat(*buf, attr->ref);
799 *buf = xmlStrcat(*buf, BAD_CAST "'");
800 }
801 } else if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
802 xmlSchemaElementPtr elem;
803
804 elem = (xmlSchemaElementPtr) item;
805 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
806 (elem->ref == NULL)) {
807 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
808 *buf = xmlStrcat(*buf, BAD_CAST " '");
809 *buf = xmlStrcat(*buf, elem->name);
810 *buf = xmlStrcat(*buf, BAD_CAST "'");
811 } else {
812 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
813 *buf = xmlStrcat(*buf, BAD_CAST " '");
814 *buf = xmlStrcat(*buf, elem->refPrefix);
815 *buf = xmlStrcat(*buf, BAD_CAST ":");
816 *buf = xmlStrcat(*buf, elem->ref);
817 *buf = xmlStrcat(*buf, BAD_CAST "'");
818 }
William M. Brack2f2a6632004-08-20 23:09:47 +0000819 } else
820 named = 0;
821 } else
822 named = 0;
823
824 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +0000825 xmlNodePtr elem;
826
827 if (itemNode->type == XML_ATTRIBUTE_NODE)
828 elem = itemNode->parent;
829 else
830 elem = itemNode;
831 *buf = xmlStrdup(BAD_CAST "Element '");
832 if (parsing)
833 *buf = xmlStrcat(*buf, elem->name);
834 else
835 *buf = xmlStrcat(*buf,
836 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
837 *buf = xmlStrcat(*buf, BAD_CAST "'");
838 }
839 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
840 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
841 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
842 itemNode->ns, itemNode->name));
843 *buf = xmlStrcat(*buf, BAD_CAST "'");
844 }
845 FREE_AND_NULL(str);
846
847 return (*buf);
848}
849
850/**
851 * xmlSchemaPFormatItemDes:
852 * @buf: the string buffer
853 * @item: the item as a schema object
854 * @itemNode: the item as a node
855 *
856 * If the pointer to @buf is not NULL and @but holds no value,
857 * the value is set to a item designation using
858 * xmlSchemaFormatItemForReport. This one avoids adding
859 * an attribute designation postfix.
860 *
861 * Returns a string of all enumeration elements.
862 */
863static void
864xmlSchemaPRequestItemDes(xmlChar **buf,
865 xmlSchemaTypePtr item,
866 xmlNodePtr itemNode)
867{
868 if ((buf == 0) || (*buf != NULL))
869 return;
870 if (itemNode->type == XML_ATTRIBUTE_NODE)
871 itemNode = itemNode->parent;
872 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
873}
874
875/**
876 * xmlSchemaFormatFacetEnumSet:
877 * @buf: the string buffer
878 * @type: the type holding the enumeration facets
879 *
880 * Builds a string consisting of all enumeration elements.
881 *
882 * Returns a string of all enumeration elements.
883 */
884static const xmlChar *
885xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
886{
887 xmlSchemaFacetLinkPtr link;
888
889 if (*buf != NULL)
890 xmlFree(*buf);
891 *buf = NULL;
892 for (link = type->facetSet; link != NULL; link = link->next) {
893 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
894 if (*buf == NULL) {
895 *buf = xmlStrdup(BAD_CAST "'");
896 *buf = xmlStrcat(*buf, link->facet->value);
897 *buf = xmlStrcat(*buf, BAD_CAST "'");
898 } else {
899 *buf = xmlStrcat(*buf, BAD_CAST ", '");
900 *buf = xmlStrcat(*buf, link->facet->value);
901 *buf = xmlStrcat(*buf, BAD_CAST "'");
902 }
903 }
904 }
905 return ((const xmlChar *) *buf);
906}
907
908/**
909 * xmlSchemaVFacetErr:
910 * @ctxt: the schema validation context
911 * @error: the error code
912 * @node: the node to be validated
913 * @value: the value of the node
914 * @type: the type holding the facet
915 * @facet: the facet
916 * @message: the error message of NULL
917 * @str1: extra data
918 * @str2: extra data
919 * @str3: extra data
920 *
921 * Reports a facet validation error.
922 * TODO: Should this report the value of an element as well?
923 */
924static void
925xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
926 xmlParserErrors error,
927 xmlNodePtr node,
928 const xmlChar *value,
929 unsigned long length,
930 xmlSchemaTypePtr type,
931 xmlSchemaFacetPtr facet,
932 const char *message,
933 const xmlChar *str1,
934 const xmlChar *str2,
935 const xmlChar *str3)
936{
937 xmlChar *str = NULL, *msg = NULL;
938 xmlSchemaTypeType facetType;
939
940 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
941 msg = xmlStrcat(msg, BAD_CAST " [");
942 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
943 msg = xmlStrcat(msg, BAD_CAST ", facet '");
944 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
945 facetType = XML_SCHEMA_FACET_ENUMERATION;
946 /*
947 * If enumerations are validated, one must not expect the
948 * facet to be given.
949 */
950 } else
951 facetType = facet->type;
952 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
953 msg = xmlStrcat(msg, BAD_CAST "']: ");
954 if (message == NULL) {
955 /*
956 * Use a default message.
957 */
958 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
959 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
960 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
961
962 char len[25], actLen[25];
963
964 /* FIXME, TODO: What is the max expected string length of the
965 * this value?
966 */
967 if (node->type == XML_ATTRIBUTE_NODE)
968 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
969 else
970 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
971
972 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
973 snprintf(actLen, 24, "%lu", length);
974
975 if (facetType == XML_SCHEMA_FACET_LENGTH)
976 msg = xmlStrcat(msg,
977 BAD_CAST "this differs from the allowed length of '%s'.\n");
978 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
979 msg = xmlStrcat(msg,
980 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
981 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
982 msg = xmlStrcat(msg,
983 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
984
985 if (node->type == XML_ATTRIBUTE_NODE)
986 xmlSchemaVErrExt(ctxt, node, error,
987 (const char *) msg,
988 value, (const xmlChar *) actLen, (const xmlChar *) len,
989 NULL, NULL);
990 else
991 xmlSchemaVErr(ctxt, node, error,
992 (const char *) msg,
993 (const xmlChar *) actLen, (const xmlChar *) len);
994
995 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
996 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
997 "of the set {%s}.\n");
998 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
999 xmlSchemaFormatFacetEnumSet(&str, type));
1000 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1001 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1002 "by the pattern '%s'.\n");
1003 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1004 facet->value);
1005 } else if (node->type == XML_ATTRIBUTE_NODE) {
1006 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1007 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1008 } else {
1009 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1010 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1011 }
1012 } else {
1013 msg = xmlStrcat(msg, (const xmlChar *) message);
1014 msg = xmlStrcat(msg, BAD_CAST ".\n");
1015 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1016 }
1017 FREE_AND_NULL(str)
1018 xmlFree(msg);
1019}
1020
1021/**
1022 * xmlSchemaVSimpleTypeErr:
1023 * @ctxt: the schema validation context
1024 * @error: the error code
1025 * @type: the type used for validation
1026 * @node: the node containing the validated value
1027 * @value: the validated value
1028 *
1029 * Reports a simple type validation error.
1030 * TODO: Should this report the value of an element as well?
1031 */
1032static void
1033xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1034 xmlParserErrors error,
1035 xmlNodePtr node,
1036 const xmlChar *value,
1037 xmlSchemaTypePtr type)
1038{
1039 xmlChar *str = NULL, *msg = NULL;
1040
1041 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1042 msg = xmlStrcat(msg, BAD_CAST " [");
1043 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1044 if (node->type == XML_ATTRIBUTE_NODE) {
1045 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1046 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1047 } else {
1048 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1049 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1050 }
1051 FREE_AND_NULL(str)
1052 xmlFree(msg);
1053}
1054
1055/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001056 * xmlSchemaVComplexTypeErr:
1057 * @ctxt: the schema validation context
1058 * @error: the error code
1059 * @node: the node containing the validated value
1060 * @type: the complex type used for validation
1061 * @message: the error message
1062 *
1063 * Reports a complex type validation error.
1064 */
1065static void
1066xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1067 xmlParserErrors error,
1068 xmlNodePtr node,
1069 xmlSchemaTypePtr type,
1070 const char *message)
1071{
1072 xmlChar *str = NULL, *msg = NULL;
1073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001074 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001075 /* Specify the complex type only if it is global. */
1076 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001077 msg = xmlStrcat(msg, BAD_CAST " [");
1078 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1079 msg = xmlStrcat(msg, BAD_CAST "]");
1080 }
1081 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
William M. Brack2f2a6632004-08-20 23:09:47 +00001082 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
1083 (const xmlChar *) message, NULL);
1084 FREE_AND_NULL(str)
1085 xmlFree(msg);
1086}
1087
1088/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001089 * xmlSchemaPMissingAttrErr:
1090 * @ctxt: the schema validation context
1091 * @ownerDes: the designation of the owner
1092 * @ownerName: the name of the owner
1093 * @ownerItem: the owner as a schema object
1094 * @ownerElem: the owner as an element node
1095 * @node: the parent element node of the missing attribute node
1096 * @type: the corresponding type of the attribute node
1097 *
1098 * Reports an illegal attribute.
1099 */
1100static void
1101xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1102 xmlParserErrors error,
1103 xmlChar **ownerDes,
1104 xmlSchemaTypePtr ownerItem,
1105 xmlNodePtr ownerElem,
1106 const char *name,
1107 const char *message)
1108{
1109 xmlChar *des = NULL;
1110
1111 if (ownerDes == NULL)
1112 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1113 else if (*ownerDes == NULL) {
1114 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1115 des = *ownerDes;
1116 } else
1117 des = *ownerDes;
1118 if (message != NULL)
1119 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1120 else
1121 xmlSchemaPErr(ctxt, ownerElem, error,
1122 "%s: The attribute '%s' is required but missing.\n",
1123 BAD_CAST des, BAD_CAST name);
1124 if (ownerDes == NULL)
1125 FREE_AND_NULL(des);
1126}
1127
William M. Brack2f2a6632004-08-20 23:09:47 +00001128/**
1129 * xmlSchemaCompTypeToString:
1130 * @type: the type of the schema item
1131 *
1132 * Returns the component name of a schema item.
1133 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001134static const char *
1135xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1136{
1137 switch (type) {
1138 case XML_SCHEMA_TYPE_SIMPLE:
1139 return("simple type definition");
1140 case XML_SCHEMA_TYPE_COMPLEX:
1141 return("complex type definition");
1142 case XML_SCHEMA_TYPE_ELEMENT:
1143 return("element declaration");
1144 case XML_SCHEMA_TYPE_ATTRIBUTE:
1145 return("attribute declaration");
1146 case XML_SCHEMA_TYPE_GROUP:
1147 return("model group definition");
1148 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1149 return("attribute group definition");
1150 case XML_SCHEMA_TYPE_NOTATION:
1151 return("notation declaration");
1152 default:
1153 return("Not a schema component");
1154 }
1155}
1156/**
1157 * xmlSchemaPResCompAttrErr:
1158 * @ctxt: the schema validation context
1159 * @error: the error code
1160 * @ownerDes: the designation of the owner
1161 * @ownerItem: the owner as a schema object
1162 * @ownerElem: the owner as an element node
1163 * @name: the name of the attribute holding the QName
1164 * @refName: the referenced local name
1165 * @refURI: the referenced namespace URI
1166 * @message: optional message
1167 *
1168 * Used to report QName attribute values that failed to resolve
1169 * to schema components.
1170 */
1171static void
1172xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1173 xmlParserErrors error,
1174 xmlChar **ownerDes,
1175 xmlSchemaTypePtr ownerItem,
1176 xmlNodePtr ownerElem,
1177 const char *name,
1178 const xmlChar *refName,
1179 const xmlChar *refURI,
1180 xmlSchemaTypeType refType,
1181 const char *refTypeStr)
1182{
1183 xmlChar *des = NULL, *strA = NULL;
1184
1185 if (ownerDes == NULL)
1186 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1187 else if (*ownerDes == NULL) {
1188 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1189 des = *ownerDes;
1190 } else
1191 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001192 if (refTypeStr == NULL)
1193 refTypeStr = xmlSchemaCompTypeToString(refType);
1194 xmlSchemaPErrExt(ctxt, ownerElem, error,
1195 NULL, NULL, NULL,
1196 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1197 "%s.\n", BAD_CAST des, BAD_CAST name,
1198 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1199 BAD_CAST refTypeStr, NULL);
1200 if (ownerDes == NULL)
1201 FREE_AND_NULL(des)
1202 FREE_AND_NULL(strA)
1203}
1204
William M. Brack2f2a6632004-08-20 23:09:47 +00001205/**
1206 * xmlSchemaPCustomAttrErr:
1207 * @ctxt: the schema parser context
1208 * @error: the error code
1209 * @ownerDes: the designation of the owner
1210 * @ownerItem: the owner as a schema object
1211 * @attr: the illegal attribute node
1212 *
1213 * Reports an illegal attribute during the parse.
1214 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001215static void
1216xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001217 xmlParserErrors error,
1218 xmlChar **ownerDes,
1219 xmlSchemaTypePtr ownerItem,
1220 xmlAttrPtr attr,
1221 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001222{
1223 xmlChar *des = NULL;
1224
1225 if (ownerDes == NULL)
1226 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1227 else if (*ownerDes == NULL) {
1228 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1229 des = *ownerDes;
1230 } else
1231 des = *ownerDes;
1232 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1233 "%s, attribute '%s': %s.\n",
1234 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1235 if (ownerDes == NULL)
1236 FREE_AND_NULL(des);
1237}
1238
1239/**
1240 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001241 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001242 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001243 * @ownerDes: the designation of the attribute's owner
1244 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001245 * @attr: the illegal attribute node
1246 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001247 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001248 */
1249static void
1250xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1251 xmlParserErrors error,
1252 xmlChar **ownerDes,
1253 xmlSchemaTypePtr ownerItem,
1254 xmlAttrPtr attr)
1255{
1256 xmlChar *des = NULL, *strA = NULL;
1257
1258 if (ownerDes == NULL)
1259 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1260 else if (*ownerDes == NULL) {
1261 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1262 des = *ownerDes;
1263 } else
1264 des = *ownerDes;
1265 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1266 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1267 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1268 if (ownerDes == NULL)
1269 FREE_AND_NULL(des);
1270 FREE_AND_NULL(strA);
1271}
1272
William M. Brack2f2a6632004-08-20 23:09:47 +00001273/**
1274 * xmlSchemaPAquireDes:
1275 * @des: the first designation
1276 * @itemDes: the second designation
1277 * @item: the schema item
1278 * @itemElem: the node of the schema item
1279 *
1280 * Creates a designation for an item.
1281 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001282static void
1283xmlSchemaPAquireDes(xmlChar **des,
1284 xmlChar **itemDes,
1285 xmlSchemaTypePtr item,
1286 xmlNodePtr itemElem)
1287{
1288 if (itemDes == NULL)
1289 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1290 else if (*itemDes == NULL) {
1291 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1292 *des = *itemDes;
1293 } else
1294 *des = *itemDes;
1295}
1296
William M. Brack2f2a6632004-08-20 23:09:47 +00001297/**
1298 * xmlSchemaPCustomErr:
1299 * @ctxt: the schema parser context
1300 * @error: the error code
1301 * @itemDes: the designation of the schema item
1302 * @item: the schema item
1303 * @itemElem: the node of the schema item
1304 * @message: the error message
1305 * @str1: an optional param for the error message
1306 * @str2: an optional param for the error message
1307 * @str3: an optional param for the error message
1308 *
1309 * Reports an error during parsing.
1310 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001311static void
1312xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1313 xmlParserErrors error,
1314 xmlChar **itemDes,
1315 xmlSchemaTypePtr item,
1316 xmlNodePtr itemElem,
1317 const char *message,
1318 const xmlChar *str1,
1319 const xmlChar *str2,
1320 const xmlChar *str3)
1321{
1322 xmlChar *des = NULL, *msg = NULL;
1323
1324 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1325 msg = xmlStrdup(BAD_CAST "%s: ");
1326 msg = xmlStrcat(msg, (const xmlChar *) message);
1327 msg = xmlStrcat(msg, BAD_CAST ".\n");
1328 if ((itemElem == NULL) && (item != NULL))
1329 itemElem = item->node;
1330 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1331 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1332 if (itemDes == NULL)
1333 FREE_AND_NULL(des);
1334 FREE_AND_NULL(msg);
1335}
1336
William M. Brack2f2a6632004-08-20 23:09:47 +00001337/**
1338 * xmlSchemaPCustomErr:
1339 * @ctxt: the schema parser context
1340 * @error: the error code
1341 * @itemDes: the designation of the schema item
1342 * @item: the schema item
1343 * @itemElem: the node of the schema item
1344 * @message: the error message
1345 * @str1: the optional param for the error message
1346 *
1347 * Reports an error during parsing.
1348 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001349static void
1350xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1351 xmlParserErrors error,
1352 xmlChar **itemDes,
1353 xmlSchemaTypePtr item,
1354 xmlNodePtr itemElem,
1355 const char *message,
1356 const xmlChar *str1)
1357{
1358 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1359 str1, NULL, NULL);
1360}
1361
William M. Brack2f2a6632004-08-20 23:09:47 +00001362/**
1363 * xmlSchemaPAttrUseErr:
1364 * @ctxt: the schema parser context
1365 * @error: the error code
1366 * @itemDes: the designation of the schema type
1367 * @item: the schema type
1368 * @itemElem: the node of the schema type
1369 * @attr: the invalid schema attribute
1370 * @message: the error message
1371 * @str1: the optional param for the error message
1372 *
1373 * Reports an attribute use error during parsing.
1374 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001375static void
1376xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1377 xmlParserErrors error,
1378 xmlChar **itemDes,
1379 xmlSchemaTypePtr item,
1380 xmlNodePtr itemElem,
1381 const xmlSchemaAttributePtr attr,
1382 const char *message,
1383 const xmlChar *str1)
1384{
1385 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1386
1387 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1388 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1389 xmlSchemaGetAttrName(attr));
1390 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1391 msg = xmlStrcat(msg, (const xmlChar *) message);
1392 msg = xmlStrcat(msg, BAD_CAST ".\n");
1393 if ((itemElem == NULL) && (item != NULL))
1394 itemElem = item->node;
1395 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1396 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1397 if (itemDes == NULL)
1398 FREE_AND_NULL(des);
1399 FREE_AND_NULL(strA);
1400 xmlFree(msg);
1401}
1402
William M. Brack2f2a6632004-08-20 23:09:47 +00001403/**
1404 * xmlSchemaPIllegalFacetAtomicErr:
1405 * @ctxt: the schema parser context
1406 * @error: the error code
1407 * @itemDes: the designation of the type
1408 * @item: the schema type
1409 * @baseItem: the base type of type
1410 * @facet: the illegal facet
1411 *
1412 * Reports an illegal facet for atomic simple types.
1413 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001414static void
1415xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1416 xmlParserErrors error,
1417 xmlChar **itemDes,
1418 xmlSchemaTypePtr item,
1419 xmlSchemaTypePtr baseItem,
1420 xmlSchemaFacetPtr facet)
1421{
1422 xmlChar *des = NULL, *strT = NULL;
1423
1424 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1425 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1426 "%s: The facet '%s' is not allowed on types derived from the "
1427 "type %s.\n",
1428 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1429 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1430 NULL, NULL);
1431 if (itemDes == NULL)
1432 FREE_AND_NULL(des);
1433 FREE_AND_NULL(strT);
1434}
1435
William M. Brack2f2a6632004-08-20 23:09:47 +00001436/**
1437 * xmlSchemaPIllegalFacetListUnionErr:
1438 * @ctxt: the schema parser context
1439 * @error: the error code
1440 * @itemDes: the designation of the schema item involved
1441 * @item: the schema item involved
1442 * @facet: the illegal facet
1443 *
1444 * Reports an illegal facet for <list> and <union>.
1445 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001446static void
1447xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1448 xmlParserErrors error,
1449 xmlChar **itemDes,
1450 xmlSchemaTypePtr item,
1451 xmlSchemaFacetPtr facet)
1452{
1453 xmlChar *des = NULL, *strT = NULL;
1454
1455 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1456 xmlSchemaPErr(ctxt, item->node, error,
1457 "%s: The facet '%s' is not allowed.\n",
1458 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1459 if (itemDes == NULL)
1460 FREE_AND_NULL(des);
1461 FREE_AND_NULL(strT);
1462}
1463
1464/**
1465 * xmlSchemaPMutualExclAttrErr:
1466 * @ctxt: the schema validation context
1467 * @error: the error code
1468 * @elemDes: the designation of the parent element node
1469 * @attr: the bad attribute node
1470 * @type: the corresponding type of the attribute node
1471 *
1472 * Reports an illegal attribute.
1473 */
1474static void
1475xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1476 xmlParserErrors error,
1477 xmlChar **ownerDes,
1478 xmlSchemaTypePtr ownerItem,
1479 xmlAttrPtr attr,
1480 const char *name1,
1481 const char *name2)
1482{
1483 xmlChar *des = NULL;
1484
1485 if (ownerDes == NULL)
1486 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1487 else if (*ownerDes == NULL) {
1488 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1489 des = *ownerDes;
1490 } else
1491 des = *ownerDes;
1492 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1493 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1494 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1495 if (ownerDes == NULL)
1496 FREE_AND_NULL(des)
1497}
1498
1499/**
1500 * xmlSchemaPSimpleTypeErr:
1501 * @ctxt: the schema validation context
1502 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001503 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001504 * @ownerDes: the designation of the owner
1505 * @ownerItem: the schema object if existent
1506 * @node: the validated node
1507 * @value: the validated value
1508 *
1509 * Reports a simple type validation error.
1510 * TODO: Should this report the value of an element as well?
1511 */
1512static void
1513xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1514 xmlParserErrors error,
1515 xmlChar **ownerDes,
1516 xmlSchemaTypePtr ownerItem,
1517 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001518 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001519 const char *typeDes,
1520 const xmlChar *value,
1521 const char *message,
1522 const xmlChar *str1,
1523 const xmlChar *str2)
1524{
William M. Brack2f2a6632004-08-20 23:09:47 +00001525 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001526
1527 if (ownerDes == NULL)
1528 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1529 else if (*ownerDes == NULL) {
1530 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1531 des = *ownerDes;
1532 } else
1533 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001534 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001535 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001536 if (message == NULL) {
1537 /*
1538 * Use default messages.
1539 */
1540 if (node->type == XML_ATTRIBUTE_NODE) {
1541 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1542 "%s, attribute '%s' [%s]: The value '%s' is not "
1543 "valid.\n",
1544 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1545 node->name), BAD_CAST typeDes, value, NULL);
1546 } else {
1547 xmlSchemaPErr(ctxt, node, error,
1548 "%s [%s]: The character content is not valid.\n",
1549 BAD_CAST des, BAD_CAST typeDes);
1550 }
1551 } else {
1552 xmlChar *msg;
1553
1554 msg = xmlStrdup(BAD_CAST "%s");
1555 if (node->type == XML_ATTRIBUTE_NODE)
1556 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1557 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1558 msg = xmlStrcat(msg, (const xmlChar *) message);
1559 msg = xmlStrcat(msg, BAD_CAST ".\n");
1560 if (node->type == XML_ATTRIBUTE_NODE) {
1561 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1562 (const char *) msg,
1563 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1564 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1565 } else {
1566 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1567 (const char *) msg,
1568 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1569 }
1570 xmlFree(msg);
1571 }
1572 /* Cleanup. */
1573 FREE_AND_NULL(strA)
1574 FREE_AND_NULL(strT)
1575 if (ownerDes == NULL)
1576 FREE_AND_NULL(des)
1577}
1578
William M. Brack2f2a6632004-08-20 23:09:47 +00001579/**
1580 * xmlSchemaPContentErr:
1581 * @ctxt: the schema parser context
1582 * @error: the error code
1583 * @onwerDes: the designation of the holder of the content
1584 * @ownerItem: the owner item of the holder of the content
1585 * @ownerElem: the node of the holder of the content
1586 * @child: the invalid child node
1587 * @message: the optional error message
1588 * @content: the optional string describing the correct content
1589 *
1590 * Reports an error concerning the content of a schema element.
1591 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001592static void
1593xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1594 xmlParserErrors error,
1595 xmlChar **ownerDes,
1596 xmlSchemaTypePtr ownerItem,
1597 xmlNodePtr ownerElem,
1598 xmlNodePtr child,
1599 const char *message,
1600 const char *content)
1601{
1602 xmlChar *des = NULL;
1603
1604 if (ownerDes == NULL)
1605 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1606 else if (*ownerDes == NULL) {
1607 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1608 des = *ownerDes;
1609 } else
1610 des = *ownerDes;
1611 if (message != NULL)
1612 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1613 "%s: %s.\n",
1614 BAD_CAST des, BAD_CAST message);
1615 else {
1616 if (content != NULL) {
1617 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1618 "%s: The content is not valid. Expected is %s.\n",
1619 BAD_CAST des, BAD_CAST content);
1620 } else {
1621 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1622 "%s: The content is not valid.\n",
1623 BAD_CAST des, NULL);
1624 }
1625 }
1626 if (ownerDes == NULL)
1627 FREE_AND_NULL(des)
1628}
1629
1630/**
1631 * xmlSchemaVIllegalAttrErr:
1632 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001633 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001634 * @attr: the illegal attribute node
1635 *
1636 * Reports an illegal attribute.
1637 */
1638static void
1639xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001640 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001641 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001642{
1643 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001644
1645 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1646 error,
1647 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001648 "%s: The attribute '%s' is not allowed.\n",
1649 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1650 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1651 FREE_AND_NULL(strE)
1652 FREE_AND_NULL(strA)
1653}
1654
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001655
1656static int
1657xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1658{
1659 switch (item->type) {
1660 case XML_SCHEMA_TYPE_COMPLEX:
1661 case XML_SCHEMA_TYPE_SIMPLE:
1662 case XML_SCHEMA_TYPE_GROUP:
1663 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1664 return(1);
1665 break;
1666 case XML_SCHEMA_TYPE_ELEMENT:
1667 if ( ((xmlSchemaElementPtr) item)->flags &
1668 XML_SCHEMAS_ELEM_GLOBAL)
1669 return(1);
1670 break;
1671 case XML_SCHEMA_TYPE_ATTRIBUTE:
1672 if ( ((xmlSchemaAttributePtr) item)->flags &
1673 XML_SCHEMAS_ATTR_GLOBAL)
1674 return(1);
1675 break;
1676 /* Note that attribute groups are always global. */
1677 default:
1678 return(1);
1679 }
1680 return (0);
1681}
1682
William M. Brack2f2a6632004-08-20 23:09:47 +00001683/**
1684 * xmlSchemaVCustomErr:
1685 * @ctxt: the schema validation context
1686 * @error: the error code
1687 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001688 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00001689 * @message: the error message
1690 * @str1: the optional param for the message
1691 *
1692 * Reports a validation error.
1693 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694static void
1695xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
1696 xmlParserErrors error,
1697 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001698 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699 const char *message,
1700 const xmlChar *str1)
1701{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001702 xmlChar *msg = NULL, *str = NULL;
1703
1704 if (node == NULL) {
1705 xmlSchemaVErr(ctxt, NULL,
1706 XML_SCHEMAV_INTERNAL,
1707 "Internal error: xmlSchemaVCustomErr, no node "
1708 "given.\n", NULL, NULL);
1709 return;
1710 }
1711 /* TODO: Are the HTML and DOCB doc nodes expected here? */
1712 if (node->type != XML_DOCUMENT_NODE) {
1713 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001714 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001715 msg = xmlStrcat(msg, BAD_CAST " [");
1716 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1717 msg = xmlStrcat(msg, BAD_CAST "]");
1718 }
1719 msg = xmlStrcat(msg, BAD_CAST ": ");
1720 } else
1721 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001722 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001723 msg = xmlStrcat(msg, BAD_CAST ".\n");
1724 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
1725 FREE_AND_NULL(msg)
1726 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001727}
1728
William M. Brack2f2a6632004-08-20 23:09:47 +00001729/**
1730 * xmlSchemaWildcardPCToString:
1731 * @pc: the type of processContents
1732 *
1733 * Returns a string representation of the type of
1734 * processContents.
1735 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001736static const char *
1737xmlSchemaWildcardPCToString(int pc)
1738{
1739 switch (pc) {
1740 case XML_SCHEMAS_ANY_SKIP:
1741 return ("skip");
1742 case XML_SCHEMAS_ANY_LAX:
1743 return ("lax");
1744 case XML_SCHEMAS_ANY_STRICT:
1745 return ("strict");
1746 default:
1747 return ("invalid process contents");
1748 }
1749}
1750
William M. Brack2f2a6632004-08-20 23:09:47 +00001751/**
1752 * xmlSchemaVWildcardErr:
1753 * @ctxt: the schema validation context
1754 * @error: the error code
1755 * @node: the validated node
1756 * @wild: the wildcard used
1757 * @message: the error message
1758 *
1759 * Reports an validation-by-wildcard error.
1760 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001761static void
1762xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
1763 xmlParserErrors error,
1764 xmlNodePtr node,
1765 xmlSchemaWildcardPtr wild,
1766 const char *message)
1767{
1768 xmlChar *des = NULL, *msg = NULL;
1769
1770 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
1771 msg = xmlStrdup(BAD_CAST "%s, [");
1772 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001773 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001774 msg = xmlStrcat(msg, (const xmlChar *) message);
1775 msg = xmlStrcat(msg, BAD_CAST ".\n");
1776 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
1777 FREE_AND_NULL(des);
1778 FREE_AND_NULL(msg);
1779}
1780
1781/**
1782 * xmlSchemaVMissingAttrErr:
1783 * @ctxt: the schema validation context
1784 * @node: the parent element node of the missing attribute node
1785 * @type: the corresponding type of the attribute node
1786 *
1787 * Reports an illegal attribute.
1788 */
1789static void
1790xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
1791 xmlNodePtr elem,
1792 xmlSchemaAttributePtr type)
1793{
1794 const xmlChar *name, *uri;
1795 xmlChar *strE = NULL, *strA = NULL;
1796
1797 if (type->ref != NULL) {
1798 name = type->ref;
1799 uri = type->refNs;
1800 } else {
1801 name = type->name;
1802 uri = type->targetNamespace;
1803 }
1804 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001805 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
1806 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001807 "%s: The attribute %s is required but missing.\n",
1808 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
1809 xmlSchemaFormatNsUriLocal(&strA, uri, name));
1810 FREE_AND_NULL(strE)
1811 FREE_AND_NULL(strA)
1812}
1813
Daniel Veillard4255d502002-04-16 15:50:10 +00001814/************************************************************************
1815 * *
1816 * Allocation functions *
1817 * *
1818 ************************************************************************/
1819
1820/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001821 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00001822 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001823 *
1824 * Allocate a new Schema structure.
1825 *
1826 * Returns the newly allocated structure or NULL in case or error
1827 */
1828static xmlSchemaPtr
1829xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
1830{
1831 xmlSchemaPtr ret;
1832
1833 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
1834 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001835 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00001836 return (NULL);
1837 }
1838 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00001839 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001840 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00001841
1842 return (ret);
1843}
1844
1845/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00001846 * xmlSchemaNewSchema:
1847 * @ctxt: a schema validation context
1848 *
1849 * Allocate a new Schema structure.
1850 *
1851 * Returns the newly allocated structure or NULL in case or error
1852 */
1853static xmlSchemaAssemblePtr
1854xmlSchemaNewAssemble(void)
1855{
1856 xmlSchemaAssemblePtr ret;
1857
1858 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
1859 if (ret == NULL) {
1860 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
1861 return (NULL);
1862 }
1863 memset(ret, 0, sizeof(xmlSchemaAssemble));
1864 ret->items = NULL;
1865 return (ret);
1866}
1867
1868/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001869 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00001870 *
1871 * Allocate a new Facet structure.
1872 *
1873 * Returns the newly allocated structure or NULL in case or error
1874 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00001875xmlSchemaFacetPtr
1876xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00001877{
1878 xmlSchemaFacetPtr ret;
1879
1880 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
1881 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00001882 return (NULL);
1883 }
1884 memset(ret, 0, sizeof(xmlSchemaFacet));
1885
1886 return (ret);
1887}
1888
1889/**
1890 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00001891 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00001892 * @node: a node
1893 *
1894 * Allocate a new annotation structure.
1895 *
1896 * Returns the newly allocated structure or NULL in case or error
1897 */
1898static xmlSchemaAnnotPtr
1899xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
1900{
1901 xmlSchemaAnnotPtr ret;
1902
1903 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
1904 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001905 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00001906 return (NULL);
1907 }
1908 memset(ret, 0, sizeof(xmlSchemaAnnot));
1909 ret->content = node;
1910 return (ret);
1911}
1912
1913/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00001914 * xmlSchemaFreeAnnot:
1915 * @annot: a schema type structure
1916 *
1917 * Deallocate a annotation structure
1918 */
1919static void
1920xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
1921{
1922 if (annot == NULL)
1923 return;
1924 xmlFree(annot);
1925}
1926
1927/**
Daniel Veillard1d913862003-11-21 00:28:39 +00001928 * xmlSchemaFreeImport:
1929 * @import: a schema import structure
1930 *
1931 * Deallocate an import structure
1932 */
1933static void
1934xmlSchemaFreeImport(xmlSchemaImportPtr import)
1935{
1936 if (import == NULL)
1937 return;
1938
1939 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00001940 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00001941 xmlFree(import);
1942}
1943
1944/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00001945 * xmlSchemaFreeInclude:
1946 * @include: a schema include structure
1947 *
1948 * Deallocate an include structure
1949 */
1950static void
1951xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
1952{
1953 if (include == NULL)
1954 return;
1955
1956 xmlFreeDoc(include->doc);
1957 xmlFree(include);
1958}
1959
1960/**
1961 * xmlSchemaFreeIncludeList:
1962 * @includes: a schema include list
1963 *
1964 * Deallocate an include structure
1965 */
1966static void
1967xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
1968{
1969 xmlSchemaIncludePtr next;
1970
1971 while (includes != NULL) {
1972 next = includes->next;
1973 xmlSchemaFreeInclude(includes);
1974 includes = next;
1975 }
1976}
1977
1978/**
Daniel Veillard4255d502002-04-16 15:50:10 +00001979 * xmlSchemaFreeNotation:
1980 * @schema: a schema notation structure
1981 *
1982 * Deallocate a Schema Notation structure.
1983 */
1984static void
1985xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
1986{
1987 if (nota == NULL)
1988 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00001989 xmlFree(nota);
1990}
1991
1992/**
1993 * xmlSchemaFreeAttribute:
1994 * @schema: a schema attribute structure
1995 *
1996 * Deallocate a Schema Attribute structure.
1997 */
1998static void
1999xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2000{
2001 if (attr == NULL)
2002 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002003 if (attr->annot != NULL)
2004 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002005 if (attr->defVal != NULL)
2006 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002007 xmlFree(attr);
2008}
2009
2010/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002011 * xmlSchemaFreeWildcardNsSet:
2012 * set: a schema wildcard namespace
2013 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002014 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002015 */
2016static void
2017xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2018{
2019 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002020
Daniel Veillard3646d642004-06-02 19:19:14 +00002021 while (set != NULL) {
2022 next = set->next;
2023 xmlFree(set);
2024 set = next;
2025 }
2026}
2027
2028/**
2029 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002030 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002031 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002032 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002033 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002034void
Daniel Veillard3646d642004-06-02 19:19:14 +00002035xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2036{
2037 if (wildcard == NULL)
2038 return;
2039 if (wildcard->annot != NULL)
2040 xmlSchemaFreeAnnot(wildcard->annot);
2041 if (wildcard->nsSet != NULL)
2042 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2043 if (wildcard->negNsSet != NULL)
2044 xmlFree(wildcard->negNsSet);
2045 xmlFree(wildcard);
2046}
2047
2048/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002049 * xmlSchemaFreeAttributeGroup:
2050 * @schema: a schema attribute group structure
2051 *
2052 * Deallocate a Schema Attribute Group structure.
2053 */
2054static void
2055xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2056{
2057 if (attr == NULL)
2058 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002059 if (attr->annot != NULL)
2060 xmlSchemaFreeAnnot(attr->annot);
2061 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2062 (attr->attributeWildcard != NULL))
2063 xmlSchemaFreeWildcard(attr->attributeWildcard);
2064
Daniel Veillard4255d502002-04-16 15:50:10 +00002065 xmlFree(attr);
2066}
2067
2068/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002069 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002070 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002071 *
2072 * Deallocate a list of schema attribute uses.
2073 */
2074static void
2075xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2076{
2077 xmlSchemaAttributeLinkPtr next;
2078
2079 while (attrUse != NULL) {
2080 next = attrUse->next;
2081 xmlFree(attrUse);
2082 attrUse = next;
2083 }
2084}
2085
2086/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002087 * xmlSchemaFreeTypeLinkList:
2088 * @alink: a type link
2089 *
2090 * Deallocate a list of types.
2091 */
2092static void
2093xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2094{
2095 xmlSchemaTypeLinkPtr next;
2096
2097 while (link != NULL) {
2098 next = link->next;
2099 xmlFree(link);
2100 link = next;
2101 }
2102}
2103
2104/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002105 * xmlSchemaFreeElement:
2106 * @schema: a schema element structure
2107 *
2108 * Deallocate a Schema Element structure.
2109 */
2110static void
2111xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2112{
2113 if (elem == NULL)
2114 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002115 if (elem->annot != NULL)
2116 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002117 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002118 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002119 if (elem->defVal != NULL)
2120 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002121 xmlFree(elem);
2122}
2123
2124/**
2125 * xmlSchemaFreeFacet:
2126 * @facet: a schema facet structure
2127 *
2128 * Deallocate a Schema Facet structure.
2129 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002130void
Daniel Veillard4255d502002-04-16 15:50:10 +00002131xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2132{
2133 if (facet == NULL)
2134 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002135 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002136 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002137 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002138 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002139 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002140 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002141 xmlFree(facet);
2142}
2143
2144/**
2145 * xmlSchemaFreeType:
2146 * @type: a schema type structure
2147 *
2148 * Deallocate a Schema Type structure.
2149 */
2150void
2151xmlSchemaFreeType(xmlSchemaTypePtr type)
2152{
2153 if (type == NULL)
2154 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002155 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002156 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002157 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002158 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002159
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002160 facet = type->facets;
2161 while (facet != NULL) {
2162 next = facet->next;
2163 xmlSchemaFreeFacet(facet);
2164 facet = next;
2165 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002167 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2168 if (type->attributeUses != NULL)
2169 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002170 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002171 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002172 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2173 /*
2174 * NOTE: The only case where an attribute wildcard
2175 * is not owned, is if a complex type inherits it
2176 * from a base type.
2177 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002178 xmlSchemaFreeWildcard(type->attributeWildcard);
2179 }
2180 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002181 if (type->memberTypes != NULL)
2182 xmlSchemaFreeTypeLinkList(type->memberTypes);
2183 if (type->facetSet != NULL) {
2184 xmlSchemaFacetLinkPtr next, link;
2185
2186 link = type->facetSet;
2187 do {
2188 next = link->next;
2189 xmlFree(link);
2190 link = next;
2191 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002192 }
2193 if (type->contModel != NULL)
2194 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002195 xmlFree(type);
2196}
2197
2198/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002199 * xmlSchemaFreeTypeList:
2200 * @type: a schema type structure
2201 *
2202 * Deallocate a Schema Type structure.
2203 */
2204static void
2205xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2206{
2207 xmlSchemaTypePtr next;
2208
2209 while (type != NULL) {
2210 next = type->redef;
2211 xmlSchemaFreeType(type);
2212 type = next;
2213 }
2214}
2215
2216/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 * xmlSchemaFree:
2218 * @schema: a schema structure
2219 *
2220 * Deallocate a Schema structure.
2221 */
2222void
2223xmlSchemaFree(xmlSchemaPtr schema)
2224{
2225 if (schema == NULL)
2226 return;
2227
Daniel Veillard4255d502002-04-16 15:50:10 +00002228 if (schema->notaDecl != NULL)
2229 xmlHashFree(schema->notaDecl,
2230 (xmlHashDeallocator) xmlSchemaFreeNotation);
2231 if (schema->attrDecl != NULL)
2232 xmlHashFree(schema->attrDecl,
2233 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2234 if (schema->attrgrpDecl != NULL)
2235 xmlHashFree(schema->attrgrpDecl,
2236 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2237 if (schema->elemDecl != NULL)
2238 xmlHashFree(schema->elemDecl,
2239 (xmlHashDeallocator) xmlSchemaFreeElement);
2240 if (schema->typeDecl != NULL)
2241 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002242 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002243 if (schema->groupDecl != NULL)
2244 xmlHashFree(schema->groupDecl,
2245 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002246 if (schema->schemasImports != NULL)
2247 xmlHashFree(schema->schemasImports,
2248 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002249 if (schema->includes != NULL) {
2250 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002252 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002254 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002255 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002256 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002257 xmlFree(schema);
2258}
2259
2260/************************************************************************
2261 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002262 * Debug functions *
2263 * *
2264 ************************************************************************/
2265
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002266#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002267
Daniel Veillard4255d502002-04-16 15:50:10 +00002268/**
2269 * xmlSchemaElementDump:
2270 * @elem: an element
2271 * @output: the file output
2272 *
2273 * Dump the element
2274 */
2275static void
2276xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002277 const xmlChar * name ATTRIBUTE_UNUSED,
2278 const xmlChar * context ATTRIBUTE_UNUSED,
2279 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002280{
2281 if (elem == NULL)
2282 return;
2283
2284 fprintf(output, "Element ");
Daniel Veillard3646d642004-06-02 19:19:14 +00002285 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2286 fprintf(output, "global ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002287 fprintf(output, ": %s ", elem->name);
2288 if (namespace != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002289 fprintf(output, "namespace '%s' ", namespace);
2290
Daniel Veillard4255d502002-04-16 15:50:10 +00002291 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002292 fprintf(output, "nillable ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002293 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002294 fprintf(output, "default ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002295 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002296 fprintf(output, "fixed ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002297 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002298 fprintf(output, "abstract ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002299 if (elem->flags & XML_SCHEMAS_ELEM_REF)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002300 fprintf(output, "ref '%s' ", elem->ref);
Daniel Veillard4255d502002-04-16 15:50:10 +00002301 if (elem->id != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002302 fprintf(output, "id '%s' ", elem->id);
Daniel Veillard4255d502002-04-16 15:50:10 +00002303 fprintf(output, "\n");
2304 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002305 fprintf(output, " ");
2306 if (elem->minOccurs != 1)
2307 fprintf(output, "min: %d ", elem->minOccurs);
2308 if (elem->maxOccurs >= UNBOUNDED)
2309 fprintf(output, "max: unbounded\n");
2310 else if (elem->maxOccurs != 1)
2311 fprintf(output, "max: %d\n", elem->maxOccurs);
2312 else
2313 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002314 }
2315 if (elem->namedType != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002316 fprintf(output, " type: %s", elem->namedType);
2317 if (elem->namedTypeNs != NULL)
2318 fprintf(output, " ns %s\n", elem->namedTypeNs);
2319 else
2320 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002321 }
2322 if (elem->substGroup != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002323 fprintf(output, " substitutionGroup: %s", elem->substGroup);
2324 if (elem->substGroupNs != NULL)
2325 fprintf(output, " ns %s\n", elem->substGroupNs);
2326 else
2327 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002328 }
2329 if (elem->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002330 fprintf(output, " default: %s", elem->value);
Daniel Veillard4255d502002-04-16 15:50:10 +00002331}
2332
2333/**
2334 * xmlSchemaAnnotDump:
2335 * @output: the file output
2336 * @annot: a annotation
2337 *
2338 * Dump the annotation
2339 */
2340static void
2341xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2342{
2343 xmlChar *content;
2344
2345 if (annot == NULL)
2346 return;
2347
2348 content = xmlNodeGetContent(annot->content);
2349 if (content != NULL) {
2350 fprintf(output, " Annot: %s\n", content);
2351 xmlFree(content);
2352 } else
2353 fprintf(output, " Annot: empty\n");
2354}
2355
2356/**
2357 * xmlSchemaTypeDump:
2358 * @output: the file output
2359 * @type: a type structure
2360 *
2361 * Dump a SchemaType structure
2362 */
2363static void
2364xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2365{
2366 if (type == NULL) {
2367 fprintf(output, "Type: NULL\n");
2368 return;
2369 }
2370 fprintf(output, "Type: ");
2371 if (type->name != NULL)
2372 fprintf(output, "%s, ", type->name);
2373 else
2374 fprintf(output, "no name");
2375 switch (type->type) {
2376 case XML_SCHEMA_TYPE_BASIC:
2377 fprintf(output, "basic ");
2378 break;
2379 case XML_SCHEMA_TYPE_SIMPLE:
2380 fprintf(output, "simple ");
2381 break;
2382 case XML_SCHEMA_TYPE_COMPLEX:
2383 fprintf(output, "complex ");
2384 break;
2385 case XML_SCHEMA_TYPE_SEQUENCE:
2386 fprintf(output, "sequence ");
2387 break;
2388 case XML_SCHEMA_TYPE_CHOICE:
2389 fprintf(output, "choice ");
2390 break;
2391 case XML_SCHEMA_TYPE_ALL:
2392 fprintf(output, "all ");
2393 break;
2394 case XML_SCHEMA_TYPE_UR:
2395 fprintf(output, "ur ");
2396 break;
2397 case XML_SCHEMA_TYPE_RESTRICTION:
2398 fprintf(output, "restriction ");
2399 break;
2400 case XML_SCHEMA_TYPE_EXTENSION:
2401 fprintf(output, "extension ");
2402 break;
2403 default:
2404 fprintf(output, "unknowntype%d ", type->type);
2405 break;
2406 }
2407 if (type->base != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002408 fprintf(output, "base %s, ", type->base);
Daniel Veillard4255d502002-04-16 15:50:10 +00002409 }
2410 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002411 case XML_SCHEMA_CONTENT_UNKNOWN:
2412 fprintf(output, "unknown ");
2413 break;
2414 case XML_SCHEMA_CONTENT_EMPTY:
2415 fprintf(output, "empty ");
2416 break;
2417 case XML_SCHEMA_CONTENT_ELEMENTS:
2418 fprintf(output, "element ");
2419 break;
2420 case XML_SCHEMA_CONTENT_MIXED:
2421 fprintf(output, "mixed ");
2422 break;
2423 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002424 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002425 break;
2426 case XML_SCHEMA_CONTENT_BASIC:
2427 fprintf(output, "basic ");
2428 break;
2429 case XML_SCHEMA_CONTENT_SIMPLE:
2430 fprintf(output, "simple ");
2431 break;
2432 case XML_SCHEMA_CONTENT_ANY:
2433 fprintf(output, "any ");
2434 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002435 }
2436 fprintf(output, "\n");
2437 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002438 fprintf(output, " ");
2439 if (type->minOccurs != 1)
2440 fprintf(output, "min: %d ", type->minOccurs);
2441 if (type->maxOccurs >= UNBOUNDED)
2442 fprintf(output, "max: unbounded\n");
2443 else if (type->maxOccurs != 1)
2444 fprintf(output, "max: %d\n", type->maxOccurs);
2445 else
2446 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002447 }
2448 if (type->annot != NULL)
2449 xmlSchemaAnnotDump(output, type->annot);
2450 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002451 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002452
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002453 fprintf(output, " subtypes: ");
2454 while (sub != NULL) {
2455 fprintf(output, "%s ", sub->name);
2456 sub = sub->next;
2457 }
2458 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002459 }
2460
2461}
2462
2463/**
2464 * xmlSchemaDump:
2465 * @output: the file output
2466 * @schema: a schema structure
2467 *
2468 * Dump a Schema structure.
2469 */
2470void
2471xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2472{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002473 if (output == NULL)
2474 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002475 if (schema == NULL) {
2476 fprintf(output, "Schemas: NULL\n");
2477 return;
2478 }
2479 fprintf(output, "Schemas: ");
2480 if (schema->name != NULL)
2481 fprintf(output, "%s, ", schema->name);
2482 else
2483 fprintf(output, "no name, ");
2484 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002485 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002486 else
2487 fprintf(output, "no target namespace");
2488 fprintf(output, "\n");
2489 if (schema->annot != NULL)
2490 xmlSchemaAnnotDump(output, schema->annot);
2491
2492 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2493 output);
2494 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002495 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002496}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002497#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002498
2499/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002500 * *
2501 * Utilities *
2502 * *
2503 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002504
Daniel Veillardc0826a72004-08-10 14:17:33 +00002505/**
2506 * xmlSchemaGetPropNode:
2507 * @node: the element node
2508 * @name: the name of the attribute
2509 *
2510 * Seeks an attribute with a name of @name in
2511 * no namespace.
2512 *
2513 * Returns the attribute or NULL if not present.
2514 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002515static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00002516xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00002517{
2518 xmlAttrPtr prop;
2519
Daniel Veillardc0826a72004-08-10 14:17:33 +00002520 if ((node == NULL) || (name == NULL))
2521 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00002522 prop = node->properties;
2523 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
2525 return(prop);
2526 prop = prop->next;
2527 }
2528 return (NULL);
2529}
2530
2531/**
2532 * xmlSchemaGetPropNodeNs:
2533 * @node: the element node
2534 * @uri: the uri
2535 * @name: the name of the attribute
2536 *
2537 * Seeks an attribute with a local name of @name and
2538 * a namespace URI of @uri.
2539 *
2540 * Returns the attribute or NULL if not present.
2541 */
2542static xmlAttrPtr
2543xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
2544{
2545 xmlAttrPtr prop;
2546
2547 if ((node == NULL) || (name == NULL))
2548 return(NULL);
2549 prop = node->properties;
2550 while (prop != NULL) {
2551 if ((prop->ns != NULL) &&
2552 xmlStrEqual(prop->name, BAD_CAST name) &&
2553 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00002554 return(prop);
2555 prop = prop->next;
2556 }
2557 return (NULL);
2558}
2559
2560static const xmlChar *
2561xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2562{
2563 xmlChar *val;
2564 const xmlChar *ret;
2565
2566 val = xmlNodeGetContent(node);
2567 if (val == NULL)
2568 return(NULL);
2569 ret = xmlDictLookup(ctxt->dict, val, -1);
2570 xmlFree(val);
2571 return(ret);
2572}
2573
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002574/**
2575 * xmlSchemaGetProp:
2576 * @ctxt: the parser context
2577 * @node: the node
2578 * @name: the property name
2579 *
2580 * Read a attribute value and internalize the string
2581 *
2582 * Returns the string or NULL if not present.
2583 */
2584static const xmlChar *
2585xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2586 const char *name)
2587{
2588 xmlChar *val;
2589 const xmlChar *ret;
2590
2591 val = xmlGetProp(node, BAD_CAST name);
2592 if (val == NULL)
2593 return(NULL);
2594 ret = xmlDictLookup(ctxt->dict, val, -1);
2595 xmlFree(val);
2596 return(ret);
2597}
2598
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002599/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00002600 * *
2601 * Parsing functions *
2602 * *
2603 ************************************************************************/
2604
2605/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002606 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002607 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002608 * @name: the element name
2609 * @ns: the element namespace
2610 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002611 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002612 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002613 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002614 */
2615static xmlSchemaElementPtr
2616xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002617 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002618{
2619 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002620
2621 if ((name == NULL) || (schema == NULL))
2622 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002623
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002624 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002625 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002626 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002627 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00002628 } else
2629 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00002630 /*
2631 * This one was removed, since top level element declarations have
2632 * the target namespace specified in targetNamespace of the <schema>
2633 * information element, even if elementFormDefault is "unqualified".
2634 */
2635
2636 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002637 if (xmlStrEqual(namespace, schema->targetNamespace))
2638 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
2639 else
2640 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002641 if ((ret != NULL) &&
2642 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002643 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00002644 }
William M. Bracke7091952004-05-11 15:09:58 +00002645 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002646
William M. Brack2f2a6632004-08-20 23:09:47 +00002647 /*
2648 * Removed since imported components will be hold by the main schema only.
2649 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002650 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002651 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002652 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002653 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002654 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00002655 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00002656 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
2657 return (ret);
2658 } else
2659 ret = NULL;
2660 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002661 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002662#ifdef DEBUG
2663 if (ret == NULL) {
2664 if (namespace == NULL)
2665 fprintf(stderr, "Unable to lookup type %s", name);
2666 else
2667 fprintf(stderr, "Unable to lookup type %s:%s", name,
2668 namespace);
2669 }
2670#endif
2671 return (ret);
2672}
2673
2674/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002675 * xmlSchemaGetType:
2676 * @schema: the schemas context
2677 * @name: the type name
2678 * @ns: the type namespace
2679 *
2680 * Lookup a type in the schemas or the predefined types
2681 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002682 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00002683 */
2684static xmlSchemaTypePtr
2685xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 const xmlChar * namespace)
2687{
Daniel Veillard4255d502002-04-16 15:50:10 +00002688 xmlSchemaTypePtr ret;
2689
2690 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002691 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002693 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002694 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 }
2697 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00002698 if (ret != NULL)
2699 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00002700 /*
2701 * Removed, since the imported components will be grafted on the
2702 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00002703 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002704 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002705 else
Daniel Veillard1d913862003-11-21 00:28:39 +00002706 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002707 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00002708 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00002709 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
2710 return (ret);
2711 } else
2712 ret = NULL;
2713 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002714 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002715#ifdef DEBUG
2716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 if (namespace == NULL)
2718 fprintf(stderr, "Unable to lookup type %s", name);
2719 else
2720 fprintf(stderr, "Unable to lookup type %s:%s", name,
2721 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002722 }
2723#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002724 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00002725}
2726
Daniel Veillard3646d642004-06-02 19:19:14 +00002727/**
2728 * xmlSchemaGetAttribute:
2729 * @schema: the context of the schema
2730 * @name: the name of the attribute
2731 * @ns: the target namespace of the attribute
2732 *
2733 * Lookup a an attribute in the schema or imported schemas
2734 *
2735 * Returns the attribute declaration or NULL if not found.
2736 */
2737static xmlSchemaAttributePtr
2738xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
2739 const xmlChar * namespace)
2740{
2741 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002742
2743 if ((name == NULL) || (schema == NULL))
2744 return (NULL);
2745
2746
2747 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
2748 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
2749 return (ret);
2750 else
2751 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002752 /*
2753 * Removed, since imported components will be hold by the main schema only.
2754 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002755 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002756 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002757 else
2758 import = xmlHashLookup(schema->schemasImports, namespace);
2759 if (import != NULL) {
2760 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
2761 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
2762 return (ret);
2763 } else
2764 ret = NULL;
2765 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002766 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002767#ifdef DEBUG
2768 if (ret == NULL) {
2769 if (namespace == NULL)
2770 fprintf(stderr, "Unable to lookup attribute %s", name);
2771 else
2772 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
2773 namespace);
2774 }
2775#endif
2776 return (ret);
2777}
2778
2779/**
2780 * xmlSchemaGetAttributeGroup:
2781 * @schema: the context of the schema
2782 * @name: the name of the attribute group
2783 * @ns: the target namespace of the attribute group
2784 *
2785 * Lookup a an attribute group in the schema or imported schemas
2786 *
2787 * Returns the attribute group definition or NULL if not found.
2788 */
2789static xmlSchemaAttributeGroupPtr
2790xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
2791 const xmlChar * namespace)
2792{
2793 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002794
2795 if ((name == NULL) || (schema == NULL))
2796 return (NULL);
2797
2798
2799 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
2800 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2801 return (ret);
2802 else
2803 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002804 /*
2805 * Removed since imported components will be hold by the main schema only.
2806 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002807 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002808 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002809 else
2810 import = xmlHashLookup(schema->schemasImports, namespace);
2811 if (import != NULL) {
2812 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
2813 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
2814 return (ret);
2815 else
2816 ret = NULL;
2817 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002818 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002819#ifdef DEBUG
2820 if (ret == NULL) {
2821 if (namespace == NULL)
2822 fprintf(stderr, "Unable to lookup attribute group %s", name);
2823 else
2824 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
2825 namespace);
2826 }
2827#endif
2828 return (ret);
2829}
2830
2831/**
2832 * xmlSchemaGetGroup:
2833 * @schema: the context of the schema
2834 * @name: the name of the group
2835 * @ns: the target namespace of the group
2836 *
2837 * Lookup a group in the schema or imported schemas
2838 *
2839 * Returns the group definition or NULL if not found.
2840 */
2841static xmlSchemaTypePtr
2842xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
2843 const xmlChar * namespace)
2844{
2845 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00002846
2847 if ((name == NULL) || (schema == NULL))
2848 return (NULL);
2849
2850
2851 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
2852 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2853 return (ret);
2854 else
2855 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00002856 /*
2857 * Removed since imported components will be hold by the main schema only.
2858 *
Daniel Veillard3646d642004-06-02 19:19:14 +00002859 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00002860 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00002861 else
2862 import = xmlHashLookup(schema->schemasImports, namespace);
2863 if (import != NULL) {
2864 ret = xmlSchemaGetGroup(import->schema, name, namespace);
2865 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
2866 return (ret);
2867 else
2868 ret = NULL;
2869 }
William M. Brack2f2a6632004-08-20 23:09:47 +00002870 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002871#ifdef DEBUG
2872 if (ret == NULL) {
2873 if (namespace == NULL)
2874 fprintf(stderr, "Unable to lookup group %s", name);
2875 else
2876 fprintf(stderr, "Unable to lookup group %s:%s", name,
2877 namespace);
2878 }
2879#endif
2880 return (ret);
2881}
2882
Daniel Veillard4255d502002-04-16 15:50:10 +00002883/************************************************************************
2884 * *
2885 * Parsing functions *
2886 * *
2887 ************************************************************************/
2888
2889#define IS_BLANK_NODE(n) \
2890 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
2891
2892/**
2893 * xmlSchemaIsBlank:
2894 * @str: a string
2895 *
2896 * Check if a string is ignorable
2897 *
2898 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
2899 */
2900static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002901xmlSchemaIsBlank(xmlChar * str)
2902{
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002904 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002905 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00002906 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002907 return (0);
2908 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00002909 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002910 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002911}
2912
2913/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002914 * xmlSchemaAddAssembledItem:
2915 * @ctxt: a schema parser context
2916 * @schema: the schema being built
2917 * @item: the item
2918 *
2919 * Add a item to the schema's list of current items.
2920 * This is used if the schema was already constructed and
2921 * new schemata need to be added to it.
2922 * *WARNING* this interface is highly subject to change.
2923 *
2924 * Returns 0 if suceeds and -1 if an internal error occurs.
2925 */
2926static int
2927xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
2928 xmlSchemaTypePtr item)
2929{
2930 static int growSize = 100;
2931 xmlSchemaAssemblePtr ass;
2932
2933 ass = ctxt->assemble;
2934 if (ass->sizeItems < 0) {
2935 /* If disabled. */
2936 return (0);
2937 }
2938 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002939 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002940 if (ass->items == NULL) {
2941 xmlSchemaPErrMemory(ctxt,
2942 "allocating new item buffer", NULL);
2943 return (-1);
2944 }
2945 ass->sizeItems = growSize;
2946 } else if (ass->sizeItems <= ass->nbItems) {
2947 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002948 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002949 ass->sizeItems * sizeof(xmlSchemaTypePtr));
2950 if (ass->items == NULL) {
2951 xmlSchemaPErrMemory(ctxt,
2952 "growing item buffer", NULL);
2953 ass->sizeItems = 0;
2954 return (-1);
2955 }
2956 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002957 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002958 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
2959 return (0);
2960}
2961
2962/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002963 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002964 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00002965 * @schema: the schema being built
2966 * @name: the item name
2967 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00002968 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00002969 * *WARNING* this interface is highly subject to change
2970 *
2971 * Returns the new struture or NULL in case of error
2972 */
2973static xmlSchemaNotationPtr
2974xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002975 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00002976{
2977 xmlSchemaNotationPtr ret = NULL;
2978 int val;
2979
2980 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
2981 return (NULL);
2982
2983 if (schema->notaDecl == NULL)
2984 schema->notaDecl = xmlHashCreate(10);
2985 if (schema->notaDecl == NULL)
2986 return (NULL);
2987
2988 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
2989 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002990 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002991 return (NULL);
2992 }
2993 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002994 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00002995 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
2996 ret);
2997 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998 /*
2999 * TODO: This should never happen, since a unique name will be computed.
3000 * If it fails, then an other internal error must have occured.
3001 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003002 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3003 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003004 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003005 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 xmlFree(ret);
3007 return (NULL);
3008 }
3009 return (ret);
3010}
3011
3012
3013/**
3014 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003015 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 * @schema: the schema being built
3017 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003018 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 *
3020 * Add an XML schema Attrribute declaration
3021 * *WARNING* this interface is highly subject to change
3022 *
3023 * Returns the new struture or NULL in case of error
3024 */
3025static xmlSchemaAttributePtr
3026xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003027 const xmlChar * name, const xmlChar * namespace,
3028 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003029{
3030 xmlSchemaAttributePtr ret = NULL;
3031 int val;
3032
3033 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3034 return (NULL);
3035
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003036#ifdef DEBUG
3037 fprintf(stderr, "Adding attribute %s\n", name);
3038 if (namespace != NULL)
3039 fprintf(stderr, " target namespace %s\n", namespace);
3040#endif
3041
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 if (schema->attrDecl == NULL)
3043 schema->attrDecl = xmlHashCreate(10);
3044 if (schema->attrDecl == NULL)
3045 return (NULL);
3046
3047 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3048 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003049 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 return (NULL);
3051 }
3052 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003053 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3054 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003055 val = xmlHashAddEntry3(schema->attrDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003056 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003057 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003058 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003059 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003060 NULL, NULL, node,
3061 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003062 xmlFree(ret);
3063 return (NULL);
3064 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003065 if (ctxt->assemble != NULL)
3066 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003067 return (ret);
3068}
3069
3070/**
3071 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003072 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003073 * @schema: the schema being built
3074 * @name: the item name
3075 *
3076 * Add an XML schema Attrribute Group declaration
3077 *
3078 * Returns the new struture or NULL in case of error
3079 */
3080static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003081xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003082 xmlSchemaPtr schema, const xmlChar * name,
3083 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003084{
3085 xmlSchemaAttributeGroupPtr ret = NULL;
3086 int val;
3087
3088 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3089 return (NULL);
3090
3091 if (schema->attrgrpDecl == NULL)
3092 schema->attrgrpDecl = xmlHashCreate(10);
3093 if (schema->attrgrpDecl == NULL)
3094 return (NULL);
3095
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003096 ret =
3097 (xmlSchemaAttributeGroupPtr)
3098 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003099 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003100 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003101 return (NULL);
3102 }
3103 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003104 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003105 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003106 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003107 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003108 xmlSchemaPCustomErr(ctxt,
3109 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3110 NULL, NULL, node,
3111 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 xmlFree(ret);
3113 return (NULL);
3114 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003115 if (ctxt->assemble != NULL)
3116 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003117 return (ret);
3118}
3119
3120/**
3121 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003122 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003123 * @schema: the schema being built
3124 * @name: the type name
3125 * @namespace: the type namespace
3126 *
3127 * Add an XML schema Element declaration
3128 * *WARNING* this interface is highly subject to change
3129 *
3130 * Returns the new struture or NULL in case of error
3131 */
3132static xmlSchemaElementPtr
3133xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003134 const xmlChar * name, const xmlChar * namespace,
3135 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003136{
3137 xmlSchemaElementPtr ret = NULL;
3138 int val;
3139
3140 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3141 return (NULL);
3142
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003143#ifdef DEBUG
3144 fprintf(stderr, "Adding element %s\n", name);
3145 if (namespace != NULL)
3146 fprintf(stderr, " target namespace %s\n", namespace);
3147#endif
3148
Daniel Veillard4255d502002-04-16 15:50:10 +00003149 if (schema->elemDecl == NULL)
3150 schema->elemDecl = xmlHashCreate(10);
3151 if (schema->elemDecl == NULL)
3152 return (NULL);
3153
3154 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3155 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003156 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003157 return (NULL);
3158 }
3159 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003160 ret->name = xmlDictLookup(ctxt->dict, name, -1);
3161 ret->targetNamespace = xmlDictLookup(ctxt->dict, namespace, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003165 if (topLevel) {
3166 xmlSchemaPCustomErr(ctxt,
3167 XML_SCHEMAP_REDEFINED_ELEMENT,
3168 NULL, NULL, node,
3169 "A global element declaration with the name '%s' does "
3170 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlFree(ret);
3172 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003173 } else {
3174 char buf[30];
3175
3176 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3177 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3178 namespace, ret);
3179 if (val != 0) {
3180 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003181 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003182 NULL, NULL, node,
3183 "Internal error: xmlSchemaAddElement, "
3184 "a dublicate element declaration with the name '%s' "
3185 "could not be added to the hash.", name);
3186 xmlFree(ret);
3187 return (NULL);
3188 }
3189 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003190
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003192 if (ctxt->assemble != NULL)
3193 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 return (ret);
3195}
3196
3197/**
3198 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003199 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 * @schema: the schema being built
3201 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003202 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003203 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003204 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003205 * *WARNING* this interface is highly subject to change
3206 *
3207 * Returns the new struture or NULL in case of error
3208 */
3209static xmlSchemaTypePtr
3210xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003211 const xmlChar * name, const xmlChar * namespace,
3212 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003213{
3214 xmlSchemaTypePtr ret = NULL;
3215 int val;
3216
3217 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3218 return (NULL);
3219
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003220#ifdef DEBUG
3221 fprintf(stderr, "Adding type %s\n", name);
3222 if (namespace != NULL)
3223 fprintf(stderr, " target namespace %s\n", namespace);
3224#endif
3225
Daniel Veillard4255d502002-04-16 15:50:10 +00003226 if (schema->typeDecl == NULL)
3227 schema->typeDecl = xmlHashCreate(10);
3228 if (schema->typeDecl == NULL)
3229 return (NULL);
3230
3231 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3232 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003233 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003234 return (NULL);
3235 }
3236 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003237 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003238 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003239 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003240 if (val != 0) {
3241 if (ctxt->includes == 0) {
3242 xmlSchemaPCustomErr(ctxt,
3243 XML_SCHEMAP_REDEFINED_TYPE,
3244 NULL, NULL, node,
3245 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003246 xmlFree(ret);
3247 return (NULL);
3248 } else {
3249 xmlSchemaTypePtr prev;
3250
3251 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3252 if (prev == NULL) {
3253 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003254 XML_ERR_INTERNAL_ERROR,
3255 "Internal error: xmlSchemaAddType, on type "
3256 "'%s'.\n",
3257 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003258 xmlFree(ret);
3259 return (NULL);
3260 }
3261 ret->redef = prev->redef;
3262 prev->redef = ret;
3263 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003264 }
3265 ret->minOccurs = 1;
3266 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003267 ret->attributeUses = NULL;
3268 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003269 if (ctxt->assemble != NULL)
3270 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003271 return (ret);
3272}
3273
3274/**
3275 * xmlSchemaAddGroup:
3276 * @ctxt: a schema validation context
3277 * @schema: the schema being built
3278 * @name: the group name
3279 *
3280 * Add an XML schema Group definition
3281 *
3282 * Returns the new struture or NULL in case of error
3283 */
3284static xmlSchemaTypePtr
3285xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003286 const xmlChar * name, xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003287{
3288 xmlSchemaTypePtr ret = NULL;
3289 int val;
3290
3291 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3292 return (NULL);
3293
3294 if (schema->groupDecl == NULL)
3295 schema->groupDecl = xmlHashCreate(10);
3296 if (schema->groupDecl == NULL)
3297 return (NULL);
3298
3299 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3300 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003301 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003302 return (NULL);
3303 }
3304 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003305 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003306 val =
3307 xmlHashAddEntry2(schema->groupDecl, name, schema->targetNamespace,
3308 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003309 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003310 xmlSchemaPCustomErr(ctxt,
3311 XML_SCHEMAP_REDEFINED_GROUP,
3312 NULL, NULL, node,
3313 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 xmlFree(ret);
3315 return (NULL);
3316 }
3317 ret->minOccurs = 1;
3318 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003319 if (ctxt->assemble != NULL)
3320 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003321 return (ret);
3322}
3323
Daniel Veillard3646d642004-06-02 19:19:14 +00003324/**
3325 * xmlSchemaNewWildcardNs:
3326 * @ctxt: a schema validation context
3327 *
3328 * Creates a new wildcard namespace constraint.
3329 *
3330 * Returns the new struture or NULL in case of error
3331 */
3332static xmlSchemaWildcardNsPtr
3333xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3334{
3335 xmlSchemaWildcardNsPtr ret;
3336
3337 ret = (xmlSchemaWildcardNsPtr)
3338 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3339 if (ret == NULL) {
3340 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3341 return (NULL);
3342 }
3343 ret->value = NULL;
3344 ret->next = NULL;
3345 return (ret);
3346}
3347
3348/**
3349 * xmlSchemaAddWildcard:
3350 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003351 * Adds a wildcard. It corresponds to a
3352 * xsd:anyAttribute and is used as storage for namespace
3353 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003354 *
3355 * Returns the new struture or NULL in case of error
3356 */
3357static xmlSchemaWildcardPtr
3358xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3359{
3360 xmlSchemaWildcardPtr ret = NULL;
3361
3362 if (ctxt == NULL)
3363 return (NULL);
3364
3365 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3366 if (ret == NULL) {
3367 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3368 return (NULL);
3369 }
3370 memset(ret, 0, sizeof(xmlSchemaWildcard));
3371 ret->minOccurs = 1;
3372 ret->maxOccurs = 1;
3373
3374 return (ret);
3375}
3376
Daniel Veillard4255d502002-04-16 15:50:10 +00003377/************************************************************************
3378 * *
3379 * Utilities for parsing *
3380 * *
3381 ************************************************************************/
3382
3383/**
3384 * xmlGetQNameProp:
3385 * @ctxt: a schema validation context
3386 * @node: a subtree containing XML Schema informations
3387 * @name: the attribute name
3388 * @namespace: the result namespace if any
3389 *
3390 * Extract a QName Attribute value
3391 *
3392 * Returns the NCName or NULL if not found, and also update @namespace
3393 * with the namespace URI
3394 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003395static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003396xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003397 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003398{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003399 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003401 const xmlChar *ret, *prefix;
3402 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003403 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003404
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003405 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003406 attr = xmlSchemaGetPropNode(node, name);
3407 if (attr == NULL)
3408 return (NULL);
3409 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003410
Daniel Veillard4255d502002-04-16 15:50:10 +00003411 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003413
Daniel Veillardba0153a2004-04-01 10:42:31 +00003414 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003415 ns = xmlSearchNs(node->doc, node, 0);
3416 if (ns) {
3417 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3418 return (val);
3419 }
3420 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003421 ret = xmlSplitQName3(val, &len);
3422 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003424 }
3425 ret = xmlDictLookup(ctxt->dict, ret, -1);
3426 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427
3428 ns = xmlSearchNs(node->doc, node, prefix);
3429 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003430 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3431 NULL, NULL, (xmlNodePtr) attr,
3432 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003433 "The QName value '%s' has no corresponding namespace "
3434 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003436 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003437 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003438 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003439}
3440
3441/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003442 * xmlSchemaPValAttrNodeQNameValue:
3443 * @ctxt: a schema parser context
3444 * @schema: the schema context
3445 * @ownerDes: the designation of the parent element
3446 * @ownerItem: the parent as a schema object
3447 * @value: the QName value
3448 * @local: the resulting local part if found, the attribute value otherwise
3449 * @uri: the resulting namespace URI if found
3450 *
3451 * Extracts the local name and the URI of a QName value and validates it.
3452 * This one is intended to be used on attribute values that
3453 * should resolve to schema components.
3454 *
3455 * Returns 0, in case the QName is valid, a positive error code
3456 * if not valid and -1 if an internal error occurs.
3457 */
3458static int
3459xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3460 xmlSchemaPtr schema,
3461 xmlChar **ownerDes,
3462 xmlSchemaTypePtr ownerItem,
3463 xmlAttrPtr attr,
3464 const xmlChar *value,
3465 const xmlChar **uri,
3466 const xmlChar **prefix,
3467 const xmlChar **local)
3468{
3469 const xmlChar *pref;
3470 xmlNsPtr ns;
3471 int len, ret;
3472
3473 *uri = NULL;
3474 *local = NULL;
3475 if (prefix != 0)
3476 *prefix = NULL;
3477 ret = xmlValidateQName(value, 1);
3478 if (ret > 0) {
3479 xmlSchemaPSimpleTypeErr(ctxt,
3480 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3481 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003482 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3483 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003484 NULL, NULL, NULL);
3485 *local = value;
3486 return (ctxt->err);
3487 } else if (ret < 0)
3488 return (-1);
3489
3490 if (!strchr((char *) value, ':')) {
3491 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3492 if (ns)
3493 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3494 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3495 /*
3496 * This one takes care of included schemas with no
3497 * target namespace.
3498 */
3499 *uri = schema->targetNamespace;
3500 }
3501 *local = value;
3502 return (0);
3503 }
3504 /*
3505 * At this point xmlSplitQName3 has to return a local name.
3506 */
3507 *local = xmlSplitQName3(value, &len);
3508 *local = xmlDictLookup(ctxt->dict, *local, -1);
3509 pref = xmlDictLookup(ctxt->dict, value, len);
3510 if (prefix != 0)
3511 *prefix = pref;
3512 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3513 if (ns == NULL) {
3514 xmlSchemaPSimpleTypeErr(ctxt,
3515 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3516 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003517 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
3518 "The QName value '%s' has no corresponding namespace "
3519 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003520 return (ctxt->err);
3521 } else {
3522 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3523 }
3524 return (0);
3525}
3526
3527/**
3528 * xmlSchemaPValAttrNodeQName:
3529 * @ctxt: a schema parser context
3530 * @schema: the schema context
3531 * @ownerDes: the designation of the owner element
3532 * @ownerItem: the owner as a schema object
3533 * @attr: the attribute node
3534 * @local: the resulting local part if found, the attribute value otherwise
3535 * @uri: the resulting namespace URI if found
3536 *
3537 * Extracts and validates the QName of an attribute value.
3538 * This one is intended to be used on attribute values that
3539 * should resolve to schema components.
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
3545xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
3546 xmlSchemaPtr schema,
3547 xmlChar **ownerDes,
3548 xmlSchemaTypePtr ownerItem,
3549 xmlAttrPtr attr,
3550 const xmlChar **uri,
3551 const xmlChar **prefix,
3552 const xmlChar **local)
3553{
3554 const xmlChar *value;
3555
3556 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
3557 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
3558 ownerDes, ownerItem, attr, value, uri, prefix, local));
3559}
3560
3561/**
3562 * xmlSchemaPValAttrQName:
3563 * @ctxt: a schema parser context
3564 * @schema: the schema context
3565 * @ownerDes: the designation of the parent element
3566 * @ownerItem: the owner as a schema object
3567 * @ownerElem: the parent node of the attribute
3568 * @name: the name of the attribute
3569 * @local: the resulting local part if found, the attribute value otherwise
3570 * @uri: the resulting namespace URI if found
3571 *
3572 * Extracts and validates the QName of an attribute value.
3573 *
3574 * Returns 0, in case the QName is valid, a positive error code
3575 * if not valid and -1 if an internal error occurs.
3576 */
3577static int
3578xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
3579 xmlSchemaPtr schema,
3580 xmlChar **ownerDes,
3581 xmlSchemaTypePtr ownerItem,
3582 xmlNodePtr ownerElem,
3583 const char *name,
3584 const xmlChar **uri,
3585 const xmlChar **prefix,
3586 const xmlChar **local)
3587{
3588 xmlAttrPtr attr;
3589
3590 attr = xmlSchemaGetPropNode(ownerElem, name);
3591 if (attr == NULL) {
3592 *local = NULL;
3593 *uri = NULL;
3594 return (0);
3595 }
3596 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
3597 ownerDes, ownerItem, attr, uri, prefix, local));
3598}
3599
3600/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003601 * xmlGetMaxOccurs:
3602 * @ctxt: a schema validation context
3603 * @node: a subtree containing XML Schema informations
3604 *
3605 * Get the maxOccurs property
3606 *
3607 * Returns the default if not found, or the value
3608 */
3609static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003610xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3611 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003612{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003613 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003615 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003616
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003617 attr = xmlSchemaGetPropNode(node, "maxOccurs");
3618 if (attr == NULL)
3619 return (def);
3620 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003621
3622 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003623 if (max != UNBOUNDED) {
3624 xmlSchemaPSimpleTypeErr(ctxt,
3625 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3626 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3627 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3628 val, NULL, NULL, NULL);
3629 return (def);
3630 } else
3631 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 }
3633
3634 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003635 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003636 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003637 if (*cur == 0) {
3638 xmlSchemaPSimpleTypeErr(ctxt,
3639 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3640 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3641 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3642 val, NULL, NULL, NULL);
3643 return (def);
3644 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 ret = ret * 10 + (*cur - '0');
3647 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 }
William M. Brack76e95df2003-10-18 16:20:14 +00003649 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003651 /*
3652 * TODO: Restrict the maximal value to Integer.
3653 */
3654 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3655 xmlSchemaPSimpleTypeErr(ctxt,
3656 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3657 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3658 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3659 val, NULL, NULL, NULL);
3660 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003663}
3664
3665/**
3666 * xmlGetMinOccurs:
3667 * @ctxt: a schema validation context
3668 * @node: a subtree containing XML Schema informations
3669 *
3670 * Get the minOccurs property
3671 *
3672 * Returns the default if not found, or the value
3673 */
3674static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003675xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3676 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003677{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003678 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003680 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003681
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003682 attr = xmlSchemaGetPropNode(node, "minOccurs");
3683 if (attr == NULL)
3684 return (def);
3685 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00003687 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003689 if (*cur == 0) {
3690 xmlSchemaPSimpleTypeErr(ctxt,
3691 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3692 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3693 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3694 val, NULL, NULL, NULL);
3695 return (def);
3696 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003698 ret = ret * 10 + (*cur - '0');
3699 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 }
William M. Brack76e95df2003-10-18 16:20:14 +00003701 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00003703 /*
3704 * TODO: Restrict the maximal value to Integer.
3705 */
3706 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
3707 xmlSchemaPSimpleTypeErr(ctxt,
3708 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3709 /* XML_SCHEMAP_INVALID_MINOCCURS, */
3710 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
3711 val, NULL, NULL, NULL);
3712 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003714 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715}
3716
3717/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003718 * xmlSchemaPGetBoolNodeValue:
3719 * @ctxt: a schema validation context
3720 * @ownerDes: owner designation
3721 * @ownerItem: the owner as a schema item
3722 * @node: the node holding the value
3723 *
3724 * Converts a boolean string value into 1 or 0.
3725 *
3726 * Returns 0 or 1.
3727 */
3728static int
3729xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
3730 xmlChar **ownerDes,
3731 xmlSchemaTypePtr ownerItem,
3732 xmlNodePtr node)
3733{
3734 xmlChar *value = NULL;
3735 int res = 0;
3736
3737 value = xmlNodeGetContent(node);
3738 /*
3739 * 3.2.2.1 Lexical representation
3740 * An instance of a datatype that is defined as ·boolean·
3741 * can have the following legal literals {true, false, 1, 0}.
3742 */
3743 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
3744 res = 1;
3745 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
3746 res = 0;
3747 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
3748 res = 1;
3749 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
3750 res = 0;
3751 else {
3752 xmlSchemaPSimpleTypeErr(ctxt,
3753 XML_SCHEMAP_INVALID_BOOLEAN,
3754 ownerDes, ownerItem, node,
3755 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3756 "(1 | 0 | true | false)", BAD_CAST value,
3757 NULL, NULL, NULL);
3758 }
3759 if (value != NULL)
3760 xmlFree(value);
3761 return (res);
3762}
3763
3764/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 * xmlGetBooleanProp:
3766 * @ctxt: a schema validation context
3767 * @node: a subtree containing XML Schema informations
3768 * @name: the attribute name
3769 * @def: the default value
3770 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003771 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 *
3773 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003774 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00003775 */
3776static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003777xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
3778 xmlChar **ownerDes,
3779 xmlSchemaTypePtr ownerItem,
3780 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003781 const char *name, int def)
3782{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003783 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003784
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003785 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003787 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 /*
3789 * 3.2.2.1 Lexical representation
3790 * An instance of a datatype that is defined as ·boolean·
3791 * can have the following legal literals {true, false, 1, 0}.
3792 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003793 if (xmlStrEqual(val, BAD_CAST "true"))
3794 def = 1;
3795 else if (xmlStrEqual(val, BAD_CAST "false"))
3796 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003797 else if (xmlStrEqual(val, BAD_CAST "1"))
3798 def = 1;
3799 else if (xmlStrEqual(val, BAD_CAST "0"))
3800 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00003801 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003802 xmlSchemaPSimpleTypeErr(ctxt,
3803 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00003804 ownerDes, ownerItem, node,
3805 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
3806 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003808 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00003809}
3810
3811/************************************************************************
3812 * *
3813 * Shema extraction from an Infoset *
3814 * *
3815 ************************************************************************/
3816static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
3817 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003818 xmlNodePtr node,
3819 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003820static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
3821 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003822 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00003823 xmlNodePtr node,
3824 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
3826 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00003827 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003828 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003829static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
3830 xmlSchemaPtr schema,
3831 xmlNodePtr node);
3832static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
3833 xmlSchemaPtr schema,
3834 xmlNodePtr node);
3835static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
3836 ctxt,
3837 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00003838 xmlNodePtr node,
3839 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003840static xmlSchemaAttributeGroupPtr
3841xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00003842 xmlSchemaPtr schema, xmlNodePtr node,
3843 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003844static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
3845 xmlSchemaPtr schema,
3846 xmlNodePtr node);
3847static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
3848 xmlSchemaPtr schema,
3849 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00003850static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003851xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
3852 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003853
3854/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003855 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003856 *
3857 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003858 * @ownerDes: the designation of the parent element
3859 * @ownerItem: the schema object owner if existent
3860 * @attr: the schema attribute node being validated
3861 * @value: the value
3862 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00003863 *
3864 * Validates a value against the given built-in type.
3865 * This one is intended to be used internally for validation
3866 * of schema attribute values during parsing of the schema.
3867 *
3868 * Returns 0 if the value is valid, a positive error code
3869 * number otherwise and -1 in case of an internal or API error.
3870 */
3871static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00003872xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
3873 xmlChar **ownerDes,
3874 xmlSchemaTypePtr ownerItem,
3875 xmlAttrPtr attr,
3876 const xmlChar *value,
3877 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003878{
Daniel Veillard01fa6152004-06-29 17:04:39 +00003879
Daniel Veillardc0826a72004-08-10 14:17:33 +00003880 int ret = 0;
3881
3882 /*
3883 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
3884 * one is really meant to be used internally, so better not.
3885 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003886 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003887 return (-1);
3888 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3889 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003890 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003891 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003892 "type '%s' is not a built-in type.\n",
3893 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003894 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00003895 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003896 switch (type->builtInType) {
3897 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003898 case XML_SCHEMAS_QNAME:
3899 case XML_SCHEMAS_ANYURI:
3900 case XML_SCHEMAS_TOKEN:
3901 case XML_SCHEMAS_LANGUAGE:
3902 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
3903 break;
3904
3905 /*
3906 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003907 ret = xmlValidateNCName(value, 1);
3908 break;
3909 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00003910 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003911 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003912 "Internal error: xmlSchemaPvalueAttrNode, use "
3913 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
3914 "for extracting QName valueues instead.\n",
3915 NULL, NULL);
3916 return (-1);
3917 case XML_SCHEMAS_ANYURI:
3918 if (value != NULL) {
3919 xmlURIPtr uri = xmlParseURI((const char *) value);
3920 if (uri == NULL)
3921 ret = 1;
3922 else
3923 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003924 }
3925 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003926 case XML_SCHEMAS_TOKEN: {
3927 const xmlChar *cur = value;
3928
3929 if (IS_BLANK_CH(*cur)) {
3930 ret = 1;
3931 } else while (*cur != 0) {
3932 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
3933 ret = 1;
3934 break;
3935 } else if (*cur == ' ') {
3936 cur++;
3937 if ((*cur == 0) || (*cur == ' ')) {
3938 ret = 1;
3939 break;
3940 }
3941 } else {
3942 cur++;
3943 }
3944 }
3945 }
3946 break;
3947 case XML_SCHEMAS_LANGUAGE:
3948 if (xmlCheckLanguageID(value) != 1)
3949 ret = 1;
3950 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003951 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003952 default: {
3953 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003954 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003955 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00003956 "valueidation using the type '%s' is not implemented "
3957 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00003958 type->name, NULL);
3959 return (-1);
3960 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003961 }
3962 /*
3963 * TODO: Should we use the S4S error codes instead?
3964 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00003965 if (ret < 0) {
3966 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
3967 XML_SCHEMAP_INTERNAL,
3968 "Internal error: xmlSchemaPValAttrNodeValue, "
3969 "failed to validate a schema attribute value.\n",
3970 NULL, NULL);
3971 return (-1);
3972 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003973 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
3974 xmlSchemaPSimpleTypeErr(ctxt,
3975 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
3976 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003977 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003978 NULL, NULL, NULL);
3979 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
3980 } else {
3981 xmlSchemaPSimpleTypeErr(ctxt,
3982 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
3983 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003985 NULL, NULL, NULL);
3986 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
3987 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003988 }
3989 return (ret);
3990}
3991
3992/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003993 * xmlSchemaPValAttrNode:
3994 *
3995 * @ctxt: a schema parser context
3996 * @ownerDes: the designation of the parent element
3997 * @ownerItem: the schema object owner if existent
3998 * @attr: the schema attribute node being validated
3999 * @type: the built-in type to be validated against
4000 * @value: the resulting value if any
4001 *
4002 * Extracts and validates a value against the given built-in type.
4003 * This one is intended to be used internally for validation
4004 * of schema attribute values during parsing of the schema.
4005 *
4006 * Returns 0 if the value is valid, a positive error code
4007 * number otherwise and -1 in case of an internal or API error.
4008 */
4009static int
4010xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4011 xmlChar **ownerDes,
4012 xmlSchemaTypePtr ownerItem,
4013 xmlAttrPtr attr,
4014 xmlSchemaTypePtr type,
4015 const xmlChar **value)
4016{
4017 const xmlChar *val;
4018
4019 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4020 return (-1);
4021
4022 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4023 if (value != NULL)
4024 *value = val;
4025
4026 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4027 val, type));
4028}
4029
4030/**
4031 * xmlSchemaPValAttr:
4032 *
4033 * @ctxt: a schema parser context
4034 * @node: the element node of the attribute
4035 * @ownerDes: the designation of the parent element
4036 * @ownerItem: the schema object owner if existent
4037 * @ownerElem: the owner element node
4038 * @name: the name of the schema attribute node
4039 * @type: the built-in type to be validated against
4040 * @value: the resulting value if any
4041 *
4042 * Extracts and validates a value against the given built-in type.
4043 * This one is intended to be used internally for validation
4044 * of schema attribute values during parsing of the schema.
4045 *
4046 * Returns 0 if the value is valid, a positive error code
4047 * number otherwise and -1 in case of an internal or API error.
4048 */
4049static int
4050xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4051 xmlChar **ownerDes,
4052 xmlSchemaTypePtr ownerItem,
4053 xmlNodePtr ownerElem,
4054 const char *name,
4055 xmlSchemaTypePtr type,
4056 const xmlChar **value)
4057{
4058 xmlAttrPtr attr;
4059
4060 if ((ctxt == NULL) || (type == NULL)) {
4061 if (value != NULL)
4062 *value = NULL;
4063 return (-1);
4064 }
4065 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4066 if (value != NULL)
4067 *value = NULL;
4068 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004069 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004070 "Internal error: xmlSchemaPValAttr, the given "
4071 "type '%s' is not a built-in type.\n",
4072 type->name, NULL);
4073 return (-1);
4074 }
4075 attr = xmlSchemaGetPropNode(ownerElem, name);
4076 if (attr == NULL) {
4077 if (value != NULL)
4078 *value = NULL;
4079 return (0);
4080 }
4081 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4082 type, value));
4083}
4084/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 * xmlSchemaParseAttrDecls:
4086 * @ctxt: a schema validation context
4087 * @schema: the schema being built
4088 * @node: a subtree containing XML Schema informations
4089 * @type: the hosting type
4090 *
4091 * parse a XML schema attrDecls declaration corresponding to
4092 * <!ENTITY % attrDecls
4093 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4094 */
4095static xmlNodePtr
4096xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4097 xmlNodePtr child, xmlSchemaTypePtr type)
4098{
4099 xmlSchemaAttributePtr lastattr, attr;
4100
4101 lastattr = NULL;
4102 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004103 (IS_SCHEMA(child, "attributeGroup"))) {
4104 attr = NULL;
4105 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004106 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004107 } else if (IS_SCHEMA(child, "attributeGroup")) {
4108 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004109 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004110 }
4111 if (attr != NULL) {
4112 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004113 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4114 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4115 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004116 type->attributes = attr;
4117 lastattr = attr;
4118 } else {
4119 lastattr->next = attr;
4120 lastattr = attr;
4121 }
4122 }
4123 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004124 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004125 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004126}
4127
4128/**
4129 * xmlSchemaParseAnnotation:
4130 * @ctxt: a schema validation context
4131 * @schema: the schema being built
4132 * @node: a subtree containing XML Schema informations
4133 *
4134 * parse a XML schema Attrribute declaration
4135 * *WARNING* this interface is highly subject to change
4136 *
William M. Bracke7091952004-05-11 15:09:58 +00004137 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004138 * 1 in case of success.
4139 */
4140static xmlSchemaAnnotPtr
4141xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4142 xmlNodePtr node)
4143{
4144 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004145 xmlNodePtr child = NULL;
4146 xmlAttrPtr attr;
4147 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004148
Daniel Veillardc0826a72004-08-10 14:17:33 +00004149 /*
4150 * INFO: S4S completed.
4151 */
4152 /*
4153 * id = ID
4154 * {any attributes with non-schema namespace . . .}>
4155 * Content: (appinfo | documentation)*
4156 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4158 return (NULL);
4159 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004160 attr = node->properties;
4161 while (attr != NULL) {
4162 if (((attr->ns == NULL) &&
4163 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4164 ((attr->ns != NULL) &&
4165 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4166
4167 xmlSchemaPIllegalAttrErr(ctxt,
4168 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4169 NULL, NULL, attr);
4170 }
4171 attr = attr->next;
4172 }
4173 /* TODO: Check id. */
4174
4175 /*
4176 * And now for the children...
4177 */
4178 child = node->children;
4179 while (child != NULL) {
4180 if (IS_SCHEMA(child, "appinfo")) {
4181 /* TODO: make available the content of "appinfo". */
4182 /*
4183 * source = anyURI
4184 * {any attributes with non-schema namespace . . .}>
4185 * Content: ({any})*
4186 */
4187 attr = child->properties;
4188 while (attr != NULL) {
4189 if (((attr->ns == NULL) &&
4190 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4191 ((attr->ns != NULL) &&
4192 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004193
Daniel Veillardc0826a72004-08-10 14:17:33 +00004194 xmlSchemaPIllegalAttrErr(ctxt,
4195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4196 NULL, NULL, attr);
4197 }
4198 attr = attr->next;
4199 }
4200 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4201 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4202 child = child->next;
4203 } else if (IS_SCHEMA(child, "documentation")) {
4204 /* TODO: make available the content of "documentation". */
4205 /*
4206 * source = anyURI
4207 * {any attributes with non-schema namespace . . .}>
4208 * Content: ({any})*
4209 */
4210 attr = child->properties;
4211 while (attr != NULL) {
4212 if (attr->ns == NULL) {
4213 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4214 xmlSchemaPIllegalAttrErr(ctxt,
4215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4216 NULL, NULL, attr);
4217 }
4218 } else {
4219 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4220 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4221 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4222
4223 xmlSchemaPIllegalAttrErr(ctxt,
4224 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4225 NULL, NULL, attr);
4226 }
4227 }
4228 attr = attr->next;
4229 }
4230 /*
4231 * Attribute "xml:lang".
4232 */
4233 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4234 if (attr != NULL)
4235 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4236 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4237 child = child->next;
4238 } else {
4239 if (!barked)
4240 xmlSchemaPContentErr(ctxt,
4241 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4242 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4243 barked = 1;
4244 child = child->next;
4245 }
4246 }
4247
Daniel Veillard4255d502002-04-16 15:50:10 +00004248 return (ret);
4249}
4250
4251/**
4252 * xmlSchemaParseFacet:
4253 * @ctxt: a schema validation context
4254 * @schema: the schema being built
4255 * @node: a subtree containing XML Schema informations
4256 *
4257 * parse a XML schema Facet declaration
4258 * *WARNING* this interface is highly subject to change
4259 *
4260 * Returns the new type structure or NULL in case of error
4261 */
4262static xmlSchemaFacetPtr
4263xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004265{
4266 xmlSchemaFacetPtr facet;
4267 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004268 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004269
4270 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4271 return (NULL);
4272
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004273 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004274 if (facet == NULL) {
4275 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4276 return (NULL);
4277 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004278 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004279 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004281 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4282 "Facet %s has no value\n", node->name, NULL);
4283 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004284 return (NULL);
4285 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004286 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004288 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004290 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004292 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004293 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004296 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004301 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004304 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004305 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4308 } else if (IS_SCHEMA(node, "minLength")) {
4309 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4310 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4312 "Unknown facet type %s\n", node->name, NULL);
4313 xmlSchemaFreeFacet(facet);
4314 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004315 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004316 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004318 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4319 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4320 const xmlChar *fixed;
4321
4322 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4323 if (fixed != NULL) {
4324 if (xmlStrEqual(fixed, BAD_CAST "true"))
4325 facet->fixed = 1;
4326 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 child = node->children;
4329
4330 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004331 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4332 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 }
4334 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4336 "Facet %s has unexpected child content\n",
4337 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 }
4339 return (facet);
4340}
4341
4342/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004343 * xmlSchemaParseWildcardNs:
4344 * @ctxt: a schema parser context
4345 * @wildc: the wildcard, already created
4346 * @node: a subtree containing XML Schema informations
4347 *
4348 * Parses the attribute "processContents" and "namespace"
4349 * of a xsd:anyAttribute and xsd:any.
4350 * *WARNING* this interface is highly subject to change
4351 *
4352 * Returns 0 if everything goes fine, a positive error code
4353 * if something is not valid and -1 if an internal error occurs.
4354 */
4355static int
4356xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4357 xmlSchemaPtr schema,
4358 xmlSchemaWildcardPtr wildc,
4359 xmlNodePtr node)
4360{
4361 const xmlChar *pc, *ns, *dictnsItem;
4362 int ret = 0;
4363 xmlChar *nsItem;
4364 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4365 xmlAttrPtr attr;
4366
4367 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4368 if ((pc == NULL)
4369 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4370 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4371 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4372 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4373 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4374 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4375 } else {
4376 xmlSchemaPSimpleTypeErr(ctxt,
4377 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4378 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004379 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 NULL, NULL, NULL);
4381 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4382 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4383 }
4384 /*
4385 * Build the namespace constraints.
4386 */
4387 attr = xmlSchemaGetPropNode(node, "namespace");
4388 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4389 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4390 wildc->any = 1;
4391 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4392 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4393 if (wildc->negNsSet == NULL) {
4394 return (-1);
4395 }
4396 wildc->negNsSet->value = schema->targetNamespace;
4397 } else {
4398 const xmlChar *end, *cur;
4399
4400 cur = ns;
4401 do {
4402 while (IS_BLANK_CH(*cur))
4403 cur++;
4404 end = cur;
4405 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4406 end++;
4407 if (end == cur)
4408 break;
4409 nsItem = xmlStrndup(cur, end - cur);
4410 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4411 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4412 xmlSchemaPSimpleTypeErr(ctxt,
4413 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4414 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004415 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004416 "((##any | ##other) | List of (anyURI | "
4417 "(##targetNamespace | ##local)))",
4418 nsItem, NULL, NULL, NULL);
4419 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4420 } else {
4421 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4422 dictnsItem = schema->targetNamespace;
4423 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4424 dictnsItem = NULL;
4425 } else {
4426 /*
4427 * Validate the item (anyURI).
4428 */
4429 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4430 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4431 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4432 }
4433 /*
4434 * Avoid dublicate namespaces.
4435 */
4436 tmp = wildc->nsSet;
4437 while (tmp != NULL) {
4438 if (dictnsItem == tmp->value)
4439 break;
4440 tmp = tmp->next;
4441 }
4442 if (tmp == NULL) {
4443 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4444 if (tmp == NULL) {
4445 xmlFree(nsItem);
4446 return (-1);
4447 }
4448 tmp->value = dictnsItem;
4449 tmp->next = NULL;
4450 if (wildc->nsSet == NULL)
4451 wildc->nsSet = tmp;
4452 else
4453 lastNs->next = tmp;
4454 lastNs = tmp;
4455 }
4456
4457 }
4458 xmlFree(nsItem);
4459 cur = end;
4460 } while (*cur != 0);
4461 }
4462 return (ret);
4463}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004464
4465static int
4466xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4467 xmlSchemaTypePtr item,
4468 xmlNodePtr node,
4469 int minOccurs,
4470 int maxOccurs) {
4471
4472 if (maxOccurs != UNBOUNDED) {
4473 /*
4474 * TODO: Maby we should better not create the particle,
4475 * if min/max is invalid, since it could confuse the build of the
4476 * content model.
4477 */
4478 /*
4479 * 3.9.6 Schema Component Constraint: Particle Correct
4480 *
4481 */
4482 if (maxOccurs < 1) {
4483 /*
4484 * 2.2 {max occurs} must be greater than or equal to 1.
4485 */
4486 xmlSchemaPCustomAttrErr(ctxt,
4487 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4488 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4489 "The value must be greater than or equal to 1");
4490 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4491 } else if (minOccurs > maxOccurs) {
4492 /*
4493 * 2.1 {min occurs} must not be greater than {max occurs}.
4494 */
4495 xmlSchemaPCustomAttrErr(ctxt,
4496 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4497 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4498 "The value must not be greater than the value of 'maxOccurs'");
4499 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4500 }
4501 }
4502 return (0);
4503}
4504
Daniel Veillardc0826a72004-08-10 14:17:33 +00004505/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004506 * xmlSchemaParseAny:
4507 * @ctxt: a schema validation context
4508 * @schema: the schema being built
4509 * @node: a subtree containing XML Schema informations
4510 *
4511 * parse a XML schema Any declaration
4512 * *WARNING* this interface is highly subject to change
4513 *
4514 * Returns the new type structure or NULL in case of error
4515 */
4516static xmlSchemaTypePtr
4517xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4518 xmlNodePtr node)
4519{
4520 xmlSchemaTypePtr type;
4521 xmlNodePtr child = NULL;
4522 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004523 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004524 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00004525
4526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4527 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004528 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
4529 "(nonNegativeInteger | unbounded)");
4530 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
4531 "nonNegativeInteger");
4532 if ((minOccurs == 0) && (maxOccurs == 0))
4533 return (NULL);
4534
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004535 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00004536 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004540 type->type = XML_SCHEMA_TYPE_ANY;
4541
Daniel Veillardc0826a72004-08-10 14:17:33 +00004542 wildc = xmlSchemaAddWildcard(ctxt);
4543 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004544 * Check min/max sanity.
4545 */
4546 type->maxOccurs = maxOccurs;
4547 type->minOccurs = minOccurs;
4548 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
4549 node, type->minOccurs, type->maxOccurs);
4550 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004551 * This is not nice, since it is won't be used as a attribute wildcard,
4552 * but better than adding a field to the structure.
4553 */
4554 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004555 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004558 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4559 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 }
4561 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004562 xmlSchemaPErr2(ctxt, node, child,
4563 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
4564 "Sequence %s has unexpected content\n", type->name,
4565 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 }
4567
4568 return (type);
4569}
4570
4571/**
4572 * xmlSchemaParseNotation:
4573 * @ctxt: a schema validation context
4574 * @schema: the schema being built
4575 * @node: a subtree containing XML Schema informations
4576 *
4577 * parse a XML schema Notation declaration
4578 *
4579 * Returns the new structure or NULL in case of error
4580 */
4581static xmlSchemaNotationPtr
4582xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004584{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004585 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00004586 xmlSchemaNotationPtr ret;
4587 xmlNodePtr child = NULL;
4588
4589 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4590 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004591 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004593 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
4594 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004595 return (NULL);
4596 }
4597 ret = xmlSchemaAddNotation(ctxt, schema, name);
4598 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004599 return (NULL);
4600 }
4601 child = node->children;
4602 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4604 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004605 }
4606 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004607 xmlSchemaPErr2(ctxt, node, child,
4608 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
4609 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004610 }
4611
4612 return (ret);
4613}
4614
4615/**
4616 * xmlSchemaParseAnyAttribute:
4617 * @ctxt: a schema validation context
4618 * @schema: the schema being built
4619 * @node: a subtree containing XML Schema informations
4620 *
4621 * parse a XML schema AnyAttrribute declaration
4622 * *WARNING* this interface is highly subject to change
4623 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004624 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00004625 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004626static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004627xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4628 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004629{
Daniel Veillard3646d642004-06-02 19:19:14 +00004630 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00004631 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004632 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004633
4634 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4635 return (NULL);
4636
Daniel Veillard3646d642004-06-02 19:19:14 +00004637 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00004638 if (ret == NULL) {
4639 return (NULL);
4640 }
William M. Bracke7091952004-05-11 15:09:58 +00004641 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004642 /*
4643 * Check for illegal attributes.
4644 */
4645 attr = node->properties;
4646 while (attr != NULL) {
4647 if (attr->ns == NULL) {
4648 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4649 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
4650 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
4651 xmlSchemaPIllegalAttrErr(ctxt,
4652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4653 NULL, NULL, attr);
4654 }
4655 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4656 xmlSchemaPIllegalAttrErr(ctxt,
4657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4658 NULL, NULL, attr);
4659 }
4660 attr = attr->next;
4661 }
4662 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
4663 /*
4664 * Parse the namespace list.
4665 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004666 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
4667 xmlSchemaFreeWildcard(ret);
4668 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004669 }
4670 /*
4671 * And now for the children...
4672 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004673 child = node->children;
4674 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004675 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4676 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004677 }
4678 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004679 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004680 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4681 NULL, NULL, node, child,
4682 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00004683 }
4684
4685 return (ret);
4686}
4687
4688
4689/**
4690 * xmlSchemaParseAttribute:
4691 * @ctxt: a schema validation context
4692 * @schema: the schema being built
4693 * @node: a subtree containing XML Schema informations
4694 *
4695 * parse a XML schema Attrribute declaration
4696 * *WARNING* this interface is highly subject to change
4697 *
William M. Bracke7091952004-05-11 15:09:58 +00004698 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00004699 */
4700static xmlSchemaAttributePtr
4701xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004702 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004703{
Daniel Veillardc0826a72004-08-10 14:17:33 +00004704 const xmlChar *name, *attrValue;
4705 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004707 xmlNodePtr child = NULL;
4708 xmlAttrPtr attr, nameAttr;
4709 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00004710
4711 /*
4712 * Note that the w3c spec assumes the schema to be validated with schema
4713 * for schemas beforehand.
4714 *
4715 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00004716 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004717
4718 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4719 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004720 attr = xmlSchemaGetPropNode(node, "ref");
4721 nameAttr = xmlSchemaGetPropNode(node, "name");
4722
4723 if ((attr == NULL) && (nameAttr == NULL)) {
4724 /*
4725 * 3.2.3 : 3.1
4726 * One of ref or name must be present, but not both
4727 */
4728 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4729 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
4730 "One of the attributes 'ref' or 'name' must be present");
4731 return (NULL);
4732 }
4733 if ((topLevel) || (attr == NULL)) {
4734 if (nameAttr == NULL) {
4735 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
4736 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
4737 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004738 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004739 }
4740 } else
4741 isRef = 1;
4742
4743 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004744 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00004745 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
4746
4747 /*
4748 * Parse as attribute reference.
4749 */
4750 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
4751 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
4752 &refPrefix, &ref) != 0) {
4753 return (NULL);
4754 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004755 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004756 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00004757 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004758 if (ret == NULL) {
4759 if (repName != NULL)
4760 xmlFree(repName);
4761 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004762 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004763 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4764 ret->node = node;
4765 ret->refNs = refNs;
4766 ret->refPrefix = refPrefix;
4767 ret->ref = ref;
4768 /*
4769 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
4770 */
4771 if (nameAttr != NULL)
4772 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
4773 &repName, (xmlSchemaTypePtr) ret, nameAttr,
4774 "ref", "name");
4775 /*
4776 * Check for illegal attributes.
4777 */
4778 attr = node->properties;
4779 while (attr != NULL) {
4780 if (attr->ns == NULL) {
4781 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
4782 xmlStrEqual(attr->name, BAD_CAST "form")) {
4783 /*
4784 * 3.2.3 : 3.2
4785 * If ref is present, then all of <simpleType>,
4786 * form and type must be absent.
4787 */
4788 xmlSchemaPIllegalAttrErr(ctxt,
4789 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
4790 (xmlSchemaTypePtr) ret, attr);
4791 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
4792 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
4793 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4794 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4795 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4796 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
4797 xmlSchemaPIllegalAttrErr(ctxt,
4798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4799 &repName, (xmlSchemaTypePtr) ret, attr);
4800 }
4801 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4802 xmlSchemaPIllegalAttrErr(ctxt,
4803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4804 &repName, (xmlSchemaTypePtr) ret, attr);
4805 }
4806 attr = attr->next;
4807 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004808 } else {
William M. Bracke7091952004-05-11 15:09:58 +00004809 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810
4811 /*
4812 * Parse as attribute declaration.
4813 */
4814 if (xmlSchemaPValAttrNode(ctxt,
4815 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
4816 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
4817 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004818 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004819 /*
4820 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
4821 */
4822 /*
4823 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
4824 */
4825 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
4826 xmlSchemaPSimpleTypeErr(ctxt,
4827 XML_SCHEMAP_NO_XMLNS,
4828 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004829 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004830 "The value must not match 'xmlns'",
4831 NULL, NULL);
4832 if (repName != NULL)
4833 xmlFree(repName);
4834 return (NULL);
4835 }
4836 /*
4837 * Evaluate the target namespace
4838 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004839 if (topLevel) {
4840 ns = schema->targetNamespace;
4841 } else {
4842 attr = xmlSchemaGetPropNode(node, "form");
4843 if (attr != NULL) {
4844 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4845 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
4846 ns = schema->targetNamespace;
4847 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
4848 xmlSchemaPSimpleTypeErr(ctxt,
4849 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4850 &repName, NULL, (xmlNodePtr) attr,
4851 NULL, "(qualified | unqualified)",
4852 attrValue, NULL, NULL, NULL);
4853 }
4854 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
4855 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004856 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004857 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004858 if (ret == NULL) {
4859 if (repName != NULL)
4860 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004861 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00004862 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004863 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
4864 ret->node = node;
4865 if (topLevel)
4866 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
4867 /*
4868 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
4869 */
4870 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
4871 xmlSchemaPCustomErr(ctxt,
4872 XML_SCHEMAP_NO_XSI,
4873 &repName, (xmlSchemaTypePtr) ret, node,
4874 "The target namespace must not match '%s'",
4875 xmlSchemaInstanceNs);
4876 }
4877 /*
4878 * Check for illegal attributes.
4879 */
4880 attr = node->properties;
4881 while (attr != NULL) {
4882 if (attr->ns == NULL) {
4883 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
4884 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
4885 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
4886 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
4887 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
4888 if ((topLevel) ||
4889 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
4890 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
4891 xmlSchemaPIllegalAttrErr(ctxt,
4892 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4893 &repName, (xmlSchemaTypePtr) ret, attr);
4894 }
4895 }
4896 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
4897 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4898 &repName, (xmlSchemaTypePtr) ret, attr);
4899 }
4900 attr = attr->next;
4901 }
4902 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
4903 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00004904 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004905 /* TODO: Check ID. */
4906 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00004907 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00004908 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00004909 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00004910 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
4911 if (ret->defValue != NULL)
4912 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
4913 /*
4914 * Attribute "default".
4915 */
4916 attr = xmlSchemaGetPropNode(node, "default");
4917 if (attr != NULL) {
4918 /*
4919 * 3.2.3 : 1
4920 * default and fixed must not both be present.
4921 */
4922 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
4923 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
4924 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
4925 } else
4926 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4927 }
4928 if (topLevel == 0) {
4929 /*
4930 * Attribute "use".
4931 */
4932 attr = xmlSchemaGetPropNode(node, "use");
4933 if (attr != NULL) {
4934 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4935 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
4936 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4937 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
4938 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
4939 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
4940 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
4941 else
4942 xmlSchemaPSimpleTypeErr(ctxt,
4943 XML_SCHEMAP_INVALID_ATTR_USE,
4944 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004945 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00004946 attrValue, NULL, NULL, NULL);
4947 } else
4948 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
4949 /*
4950 * 3.2.3 : 2
4951 * If default and use are both present, use must have
4952 * the actual value optional.
4953 */
4954 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
4955 (ret->defValue != NULL) &&
4956 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
4957 xmlSchemaPSimpleTypeErr(ctxt,
4958 XML_SCHEMAP_SRC_ATTRIBUTE_2,
4959 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004960 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004961 "The value must be 'optional' if the attribute "
4962 "'default' is present as well", NULL, NULL);
4963 }
4964 }
4965 /*
4966 * And now for the children...
4967 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004968 child = node->children;
4969 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004970 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4971 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004972 }
4973 if (isRef) {
4974 if (child != NULL) {
4975 if (IS_SCHEMA(child, "simpleType"))
4976 /*
4977 * 3.2.3 : 3.2
4978 * If ref is present, then all of <simpleType>,
4979 * form and type must be absent.
4980 */
4981 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
4982 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4983 "(annotation?)");
4984 else
4985 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4986 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
4987 "(annotation?)");
4988 }
4989 } else {
4990 if (IS_SCHEMA(child, "simpleType")) {
4991 if (ret->typeName != NULL) {
4992 /*
4993 * 3.2.3 : 4
4994 * type and <simpleType> must not both be present.
4995 */
4996 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
4997 &repName, (xmlSchemaTypePtr) ret, node, child,
4998 "The attribute 'type' and the <simpleType> child "
4999 "are mutually exclusive", NULL);
5000 } else
5001 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5002 child = child->next;
5003 }
5004 if (child != NULL)
5005 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5006 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5007 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005008 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 /*
5010 * Cleanup.
5011 */
5012 if (repName != NULL)
5013 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 return (ret);
5015}
5016
5017/**
5018 * xmlSchemaParseAttributeGroup:
5019 * @ctxt: a schema validation context
5020 * @schema: the schema being built
5021 * @node: a subtree containing XML Schema informations
5022 *
5023 * parse a XML schema Attribute Group declaration
5024 * *WARNING* this interface is highly subject to change
5025 *
5026 * Returns the attribute group or NULL in case of error.
5027 */
5028static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005030 xmlSchemaPtr schema, xmlNodePtr node,
5031 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005032{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005033 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005034 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005035 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005036 const xmlChar *oldcontainer;
5037 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005038
5039 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5040 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005041
5042 nameAttr = xmlSchemaGetPropNode(node, "name");
5043 attr = xmlSchemaGetPropNode(node, "ref");
5044 if ((topLevel) || (attr == NULL)) {
5045 /*
5046 * Parse as an attribute group definition.
5047 * Note that those are allowed at top level only.
5048 */
5049 if (nameAttr == NULL) {
5050 xmlSchemaPMissingAttrErr(ctxt,
5051 XML_SCHEMAP_S4S_ATTR_MISSING,
5052 NULL, NULL, node, "name", NULL);
5053 return (NULL);
5054 }
5055 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5056 /*
5057 * The name is crucial, exit if invalid.
5058 */
5059 if (xmlSchemaPValAttrNode(ctxt,
5060 NULL, NULL, nameAttr,
5061 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5062 return (NULL);
5063 }
5064 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5065 if (ret == NULL)
5066 return (NULL);
5067 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5068 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5069 ret->node = node;
5070 } else {
5071 char buf[50];
5072 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5073
5074 /*
5075 * Parse as an attribute group definition reference.
5076 */
5077 if (attr == NULL) {
5078 xmlSchemaPMissingAttrErr(ctxt,
5079 XML_SCHEMAP_S4S_ATTR_MISSING,
5080 NULL, NULL, node, "ref", NULL);
5081 }
5082 xmlSchemaPValAttrNodeQName(ctxt, schema,
5083 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5084
5085 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5086 name = (const xmlChar *) buf;
5087 if (name == NULL) {
5088 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5089 "attribute group definition reference", node);
5090 return (NULL);
5091 }
5092 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5093 if (ret == NULL)
5094 return (NULL);
5095 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5096 ret->ref = ref;
5097 ret->refNs = refNs;
5098 /* TODO: Is @refPrefix currently used? */
5099 ret->refPrefix = refPrefix;
5100 ret->node = node;
5101 }
5102 /*
5103 * Check for illegal attributes.
5104 */
5105 attr = node->properties;
5106 while (attr != NULL) {
5107 if (attr->ns == NULL) {
5108 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5109 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5110 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5111 {
5112 xmlSchemaPIllegalAttrErr(ctxt,
5113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5114 NULL, NULL, attr);
5115 }
5116 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5117 xmlSchemaPIllegalAttrErr(ctxt,
5118 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5119 NULL, NULL, attr);
5120 }
5121 attr = attr->next;
5122 }
5123 /* TODO: Validate "id" ? */
5124 /*
5125 * And now for the children...
5126 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005129 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005130 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005134 if (topLevel) {
5135 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5136 if (IS_SCHEMA(child, "anyAttribute")) {
5137 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5138 child = child->next;
5139 }
5140 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005141 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005142 xmlSchemaPContentErr(ctxt,
5143 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5144 NULL, NULL, node, child, NULL,
5145 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005147 ctxt->container = oldcontainer;
5148 return (ret);
5149}
5150
5151/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005152 * xmlSchemaPValAttrFormDefault:
5153 * @value: the value
5154 * @flags: the flags to be modified
5155 * @flagQualified: the specific flag for "qualified"
5156 *
5157 * Returns 0 if the value is valid, 1 otherwise.
5158 */
5159static int
5160xmlSchemaPValAttrFormDefault(const xmlChar *value,
5161 int *flags,
5162 int flagQualified)
5163{
5164 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5165 if ((*flags & flagQualified) == 0)
5166 *flags |= flagQualified;
5167 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5168 return (1);
5169
5170 return (0);
5171}
5172
5173/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005174 * xmlSchemaPValAttrBlockFinal:
5175 * @value: the value
5176 * @flags: the flags to be modified
5177 * @flagAll: the specific flag for "#all"
5178 * @flagExtension: the specific flag for "extension"
5179 * @flagRestriction: the specific flag for "restriction"
5180 * @flagSubstitution: the specific flag for "substitution"
5181 * @flagList: the specific flag for "list"
5182 * @flagUnion: the specific flag for "union"
5183 *
5184 * Validates the value of the attribute "final" and "block". The value
5185 * is converted into the specified flag values and returned in @flags.
5186 *
5187 * Returns 0 if the value is valid, 1 otherwise.
5188 */
5189
5190static int
5191xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5192 int *flags,
5193 int flagAll,
5194 int flagExtension,
5195 int flagRestriction,
5196 int flagSubstitution,
5197 int flagList,
5198 int flagUnion)
5199{
5200 int ret = 0;
5201
5202 /*
5203 * TODO: This does not check for dublicate entries.
5204 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005205 if (value == NULL)
5206 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005207 if (xmlStrEqual(value, BAD_CAST "#all")) {
5208 if (flagAll != -1)
5209 *flags |= flagAll;
5210 else {
5211 if (flagExtension != -1)
5212 *flags |= flagExtension;
5213 if (flagRestriction != -1)
5214 *flags |= flagRestriction;
5215 if (flagSubstitution != -1)
5216 *flags |= flagSubstitution;
5217 if (flagList != -1)
5218 *flags |= flagList;
5219 if (flagUnion != -1)
5220 *flags |= flagUnion;
5221 }
5222 } else {
5223 const xmlChar *end, *cur = value;
5224 xmlChar *item;
5225
5226 do {
5227 while (IS_BLANK_CH(*cur))
5228 cur++;
5229 end = cur;
5230 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5231 end++;
5232 if (end == cur)
5233 break;
5234 item = xmlStrndup(cur, end - cur);
5235 if (xmlStrEqual(item, BAD_CAST "extension")) {
5236 if (flagExtension != -1) {
5237 if ((*flags & flagExtension) == 0)
5238 *flags |= flagExtension;
5239 } else
5240 ret = 1;
5241 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5242 if (flagRestriction != -1) {
5243 if ((*flags & flagRestriction) == 0)
5244 *flags |= flagRestriction;
5245 } else
5246 ret = 1;
5247 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5248 if (flagSubstitution != -1) {
5249 if ((*flags & flagSubstitution) == 0)
5250 *flags |= flagSubstitution;
5251 } else
5252 ret = 1;
5253 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5254 if (flagList != -1) {
5255 if ((*flags & flagList) == 0)
5256 *flags |= flagList;
5257 } else
5258 ret = 1;
5259 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5260 if (flagUnion != -1) {
5261 if ((*flags & flagUnion) == 0)
5262 *flags |= flagUnion;
5263 } else
5264 ret = 1;
5265 } else
5266 ret = 1;
5267 if (item != NULL)
5268 xmlFree(item);
5269 cur = end;
5270 } while ((ret == 0) && (*cur != 0));
5271 }
5272
5273 return (ret);
5274}
5275
5276/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005277 * xmlSchemaParseElement:
5278 * @ctxt: a schema validation context
5279 * @schema: the schema being built
5280 * @node: a subtree containing XML Schema informations
5281 *
5282 * parse a XML schema Element declaration
5283 * *WARNING* this interface is highly subject to change
5284 *
William M. Bracke7091952004-05-11 15:09:58 +00005285 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 */
5287static xmlSchemaElementPtr
5288xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005289 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005290{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005291 const xmlChar *name = NULL;
5292 const xmlChar *attrValue;
5293 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005294 xmlSchemaElementPtr ret;
5295 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005296 const xmlChar *oldcontainer;
5297 xmlAttrPtr attr, nameAttr;
5298 int minOccurs, maxOccurs;
5299 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005300
5301 /* 3.3.3 Constraints on XML Representations of Element Declarations */
5302 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005303
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5305 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005306
Daniel Veillardc0826a72004-08-10 14:17:33 +00005307 oldcontainer = ctxt->container;
5308
5309 nameAttr = xmlSchemaGetPropNode(node, "name");
5310 attr = xmlSchemaGetPropNode(node, "ref");
5311 if ((topLevel) || (attr == NULL)) {
5312 if (nameAttr == NULL) {
5313 xmlSchemaPMissingAttrErr(ctxt,
5314 XML_SCHEMAP_S4S_ATTR_MISSING,
5315 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
5316 "name", NULL);
5317 return (NULL);
5318 }
5319 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5320 } else {
5321 isRef = 1;
5322
5323 }
5324 /*
5325 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
5326 * to no component at all
5327 * TODO: It might be better to validate the element, even if it won't be
5328 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005329 */
5330 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
5331 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005332 if ((minOccurs == 0) && (maxOccurs == 0))
5333 return (NULL);
5334 /*
5335 * If we get a "ref" attribute on a local <element> we will assume it's
5336 * a reference - even if there's a "name" attribute; this seems to be more
5337 * robust.
5338 */
5339 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005340 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5342
5343 /*
5344 * Parse as a particle.
5345 */
5346 xmlSchemaPValAttrNodeQName(ctxt, schema,
5347 (xmlChar **) &xmlSchemaElemDesAttrRef,
5348 NULL, attr, &refNs, &refPrefix, &ref);
5349
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005350 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005351 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 if (ret == NULL) {
5353 if (repName != NULL)
5354 xmlFree(repName);
5355 return (NULL);
5356 }
5357 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5358 ret->node = node;
5359 ret->ref = ref;
5360 ret->refNs = refNs;
5361 ret->refPrefix = refPrefix;
5362 ret->flags |= XML_SCHEMAS_ELEM_REF;
5363 /*
5364 * Check for illegal attributes.
5365 */
5366 /*
5367 * 3.3.3 : 2.1
5368 * One of ref or name must be present, but not both
5369 */
5370 if (nameAttr != NULL) {
5371 xmlSchemaPMutualExclAttrErr(ctxt,
5372 XML_SCHEMAP_SRC_ELEMENT_2_1,
5373 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5374 "ref", "name");
5375 }
5376 /* 3.3.3 : 2.2 */
5377 attr = node->properties;
5378 while (attr != NULL) {
5379 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005380 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
5381 xmlStrEqual(attr->name, BAD_CAST "name") ||
5382 xmlStrEqual(attr->name, BAD_CAST "id") ||
5383 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
5384 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
5385 {
5386 attr = attr->next;
5387 continue;
5388 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005389 xmlSchemaPCustomAttrErr(ctxt,
5390 XML_SCHEMAP_SRC_ELEMENT_2_2,
5391 &repName, (xmlSchemaTypePtr) ret, attr,
5392 "Only the attributes 'minOccurs', 'maxOccurs' and "
5393 "'id' are allowed in addition to 'ref'");
5394 break;
5395 }
5396 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5397 xmlSchemaPIllegalAttrErr(ctxt,
5398 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5399 &repName, (xmlSchemaTypePtr) ret, attr);
5400 }
5401 attr = attr->next;
5402 }
5403 } else {
5404 const xmlChar *ns = NULL, *fixed;
5405
5406 /*
5407 * Parse as an element declaration.
5408 */
5409 if (xmlSchemaPValAttrNode(ctxt,
5410 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
5411 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
5412 return (NULL);
5413 /*
5414 * Evaluate the target namespace.
5415 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005416 if (topLevel) {
5417 ns = schema->targetNamespace;
5418 } else {
5419 attr = xmlSchemaGetPropNode(node, "form");
5420 if (attr != NULL) {
5421 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5422 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00005423 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005424 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5425 xmlSchemaPSimpleTypeErr(ctxt,
5426 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5427 &repName, NULL, (xmlNodePtr) attr,
5428 NULL, "(qualified | unqualified)",
5429 attrValue, NULL, NULL, NULL);
5430 }
5431 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
5432 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00005433 }
5434 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 if (ret == NULL) {
5436 if (repName != NULL)
5437 xmlFree(repName);
5438 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005439 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005440 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5441 ret->node = node;
5442 /*
5443 * Check for illegal attributes.
5444 */
William M. Bracke7091952004-05-11 15:09:58 +00005445 attr = node->properties;
5446 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005447 if (attr->ns == NULL) {
5448 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5449 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
5450 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5451 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5452 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5453 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005454 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
5455 {
5456 if (topLevel == 0) {
5457 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005458 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005459 (!xmlStrEqual(attr->name, BAD_CAST "form")))
5460 {
5461 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
5462 /*
5463 * 3.3.6 : 3 If there is a non-·absent· {substitution
5464 * group affiliation}, then {scope} must be global.
5465 * TODO: This one is redundant, since the S4S does
5466 * prohibit this attribute on local declarations already;
5467 * so why an explicit error code? Weird spec.
5468 * TODO: Move this to the proper constraint layer.
5469 * TODO: Or better wait for spec 1.1 to come.
5470 */
5471 xmlSchemaPIllegalAttrErr(ctxt,
5472 XML_SCHEMAP_E_PROPS_CORRECT_3,
5473 &repName, (xmlSchemaTypePtr) ret, attr);
5474 } else {
5475 xmlSchemaPIllegalAttrErr(ctxt,
5476 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5477 &repName, (xmlSchemaTypePtr) ret, attr);
5478 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005479 }
5480 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
5481 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
5482 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
5483
5484 xmlSchemaPIllegalAttrErr(ctxt,
5485 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5486 &repName, (xmlSchemaTypePtr) ret, attr);
5487 }
5488 }
5489 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5490
5491 xmlSchemaPIllegalAttrErr(ctxt,
5492 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5493 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00005494 }
5495 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 }
William M. Bracke7091952004-05-11 15:09:58 +00005497 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 * Extract/validate attributes.
5499 */
5500 if (topLevel) {
5501 /*
5502 * Process top attributes of global element declarations here.
5503 */
5504 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
5505 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
5506 xmlSchemaPValAttrQName(ctxt, schema, &repName,
5507 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
5508 &(ret->substGroupNs), NULL, &(ret->substGroup));
5509 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5510 node, "abstract", 0))
5511 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
5512 /*
5513 * Attribute "final".
5514 */
5515 attr = xmlSchemaGetPropNode(node, "final");
5516 if (attr == NULL) {
5517 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
5518 } else {
5519 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5520 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5521 -1,
5522 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
5523 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
5524 xmlSchemaPSimpleTypeErr(ctxt,
5525 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5526 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005527 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005528 attrValue, NULL, NULL, NULL);
5529 }
5530 }
5531 }
5532 /*
5533 * Attribute "block".
5534 */
5535 attr = xmlSchemaGetPropNode(node, "block");
5536 if (attr == NULL) {
5537 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
5538 } else {
5539 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5540 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
5541 -1,
5542 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
5543 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
5544 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
5545 xmlSchemaPSimpleTypeErr(ctxt,
5546 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5547 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005548 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 "restriction | substitution))", attrValue,
5550 NULL, NULL, NULL);
5551 }
5552 }
5553 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
5554 node, "nillable", 0))
5555 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005556
Daniel Veillardc0826a72004-08-10 14:17:33 +00005557 xmlSchemaPValAttrQName(ctxt, schema,
5558 &repName, (xmlSchemaTypePtr) ret, node,
5559 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00005560
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 ret->value = xmlSchemaGetProp(ctxt, node, "default");
5562 attr = xmlSchemaGetPropNode(node, "fixed");
5563 if (attr != NULL) {
5564 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5565 if (ret->value != NULL) {
5566 /*
5567 * 3.3.3 : 1
5568 * default and fixed must not both be present.
5569 */
5570 xmlSchemaPMutualExclAttrErr(ctxt,
5571 XML_SCHEMAP_SRC_ELEMENT_1,
5572 &repName, (xmlSchemaTypePtr) ret, attr,
5573 "default", "fixed");
5574 } else {
5575 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
5576 ret->value = fixed;
5577 }
5578 }
5579 }
5580 /*
5581 * Extract/validate common attributes.
5582 */
5583 /* TODO: Check ID: */
5584 ret->id = xmlSchemaGetProp(ctxt, node, "id");
5585 ret->minOccurs = minOccurs;
5586 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005587 if (topLevel != 1)
5588 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
5589 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 /*
5591 * And now for the children...
5592 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005593 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005594 child = node->children;
5595 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5597 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005599 if (isRef) {
5600 if (child != NULL) {
5601 xmlSchemaPContentErr(ctxt,
5602 XML_SCHEMAP_SRC_ELEMENT_2_2,
5603 &repName, (xmlSchemaTypePtr) ret, node, child,
5604 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00005605 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005606 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005607 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 /*
5609 * 3.3.3 : 3
5610 * "type" and either <simpleType> or <complexType> are mutually
5611 * exclusive
5612 */
William M. Bracke7091952004-05-11 15:09:58 +00005613 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 xmlSchemaPContentErr(ctxt,
5615 XML_SCHEMAP_SRC_ELEMENT_3,
5616 &repName, (xmlSchemaTypePtr) ret, node, child,
5617 "The attribute 'type' and the <complexType> child are "
5618 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005619 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005620 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005621 child = child->next;
5622 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005623 /*
5624 * 3.3.3 : 3
5625 * "type" and either <simpleType> or <complexType> are
5626 * mutually exclusive
5627 */
William M. Bracke7091952004-05-11 15:09:58 +00005628 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 xmlSchemaPContentErr(ctxt,
5630 XML_SCHEMAP_SRC_ELEMENT_3,
5631 &repName, (xmlSchemaTypePtr) ret, node, child,
5632 "The attribute 'type' and the <simpleType> child are "
5633 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005634 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00005635 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00005636 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005637 }
William M. Bracke7091952004-05-11 15:09:58 +00005638 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcik48307f42004-11-12 15:16:25 +00005640 TODO child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00005641 }
5642 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005643 xmlSchemaPContentErr(ctxt,
5644 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5645 &repName, (xmlSchemaTypePtr) ret, node, child,
5646 NULL, "(annotation?, ((simpleType | complexType)?, "
5647 "(unique | key | keyref)*))");
5648 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005649
Daniel Veillardc0826a72004-08-10 14:17:33 +00005650 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005651 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005652 /*
5653 * Cleanup.
5654 */
5655 if (repName != NULL)
5656 xmlFree(repName);
5657 /*
5658 * NOTE: Element Declaration Representation OK 4. will be checked at a
5659 * different layer.
5660 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 return (ret);
5662}
5663
5664/**
5665 * xmlSchemaParseUnion:
5666 * @ctxt: a schema validation context
5667 * @schema: the schema being built
5668 * @node: a subtree containing XML Schema informations
5669 *
5670 * parse a XML schema Union definition
5671 * *WARNING* this interface is highly subject to change
5672 *
William M. Bracke7091952004-05-11 15:09:58 +00005673 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 * 1 in case of success.
5675 */
5676static xmlSchemaTypePtr
5677xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005678 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005679{
5680 xmlSchemaTypePtr type, subtype, last = NULL;
5681 xmlNodePtr child = NULL;
5682 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005683 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005684
5685 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5686 return (NULL);
5687
William M. Brack2f2a6632004-08-20 23:09:47 +00005688 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
5689 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 if (type == NULL)
5691 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00005692 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00005693 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00005694 /*
5695 * Check for illegal attributes.
5696 */
5697 attr = node->properties;
5698 while (attr != NULL) {
5699 if (attr->ns == NULL) {
5700 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5701 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
5702 xmlSchemaPIllegalAttrErr(ctxt,
5703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5704 NULL, type, attr);
5705 }
5706 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5707 xmlSchemaPIllegalAttrErr(ctxt,
5708 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5709 NULL, type, attr);
5710 }
5711 attr = attr->next;
5712 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005713 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005714 /*
5715 * Attribute "memberTypes". This is a list of QNames.
5716 * TODO: Validate the QNames.
5717 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005718 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00005719 /*
5720 * And now for the children...
5721 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005722 child = node->children;
5723 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005724 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5725 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005726 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005727 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005728 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005729 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005730 if (subtype != NULL) {
5731 if (last == NULL) {
5732 type->subtypes = subtype;
5733 last = subtype;
5734 } else {
5735 last->next = subtype;
5736 last = subtype;
5737 }
5738 last->next = NULL;
5739 }
5740 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005741 }
5742 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005743 /* TODO: Think about the error code. */
5744 xmlSchemaPContentErr(ctxt,
5745 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
5746 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005747 }
5748 return (type);
5749}
5750
5751/**
5752 * xmlSchemaParseList:
5753 * @ctxt: a schema validation context
5754 * @schema: the schema being built
5755 * @node: a subtree containing XML Schema informations
5756 *
5757 * parse a XML schema List definition
5758 * *WARNING* this interface is highly subject to change
5759 *
William M. Bracke7091952004-05-11 15:09:58 +00005760 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 * 1 in case of success.
5762 */
5763static xmlSchemaTypePtr
5764xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005765 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005766{
5767 xmlSchemaTypePtr type, subtype;
5768 xmlNodePtr child = NULL;
5769 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00005770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005771
5772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5773 return (NULL);
5774
William M. Brack2f2a6632004-08-20 23:09:47 +00005775 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
5776 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005777 if (type == NULL)
5778 return (NULL);
5779 type->node = node;
5780 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005781 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00005782 /*
5783 * Check for illegal attributes.
5784 */
5785 attr = node->properties;
5786 while (attr != NULL) {
5787 if (attr->ns == NULL) {
5788 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5789 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
5790 xmlSchemaPIllegalAttrErr(ctxt,
5791 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5792 NULL, type, attr);
5793 }
5794 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5795 xmlSchemaPIllegalAttrErr(ctxt,
5796 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5797 NULL, type, attr);
5798 }
5799 attr = attr->next;
5800 }
5801 /*
5802 * Attribute "itemType".
5803 */
5804 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
5805 node, "itemType", &(type->baseNs), NULL, &(type->base));
5806 /*
5807 * And now for the children...
5808 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 child = node->children;
5810 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5812 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00005813 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00005815 if (IS_SCHEMA(child, "simpleType")) {
5816 if (type->base != NULL) {
5817 xmlSchemaPCustomErr(ctxt,
5818 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
5819 NULL, type, node,
5820 "The attribute 'itemType' and the <simpleType> child "
5821 "are mutually exclusive", NULL);
5822 } else {
5823 subtype = (xmlSchemaTypePtr)
5824 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5825 type->subtypes = subtype;
5826 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005827 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005828 }
5829 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005830 /* TODO: Think about the error code. */
5831 xmlSchemaPContentErr(ctxt,
5832 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
5833 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005834 }
5835 return (type);
5836}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005837
Daniel Veillard4255d502002-04-16 15:50:10 +00005838/**
5839 * xmlSchemaParseSimpleType:
5840 * @ctxt: a schema validation context
5841 * @schema: the schema being built
5842 * @node: a subtree containing XML Schema informations
5843 *
5844 * parse a XML schema Simple Type definition
5845 * *WARNING* this interface is highly subject to change
5846 *
William M. Bracke7091952004-05-11 15:09:58 +00005847 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00005848 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 */
5850static xmlSchemaTypePtr
5851xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005852 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005853{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005854 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00005855 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005856 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005857 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005859
5860 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5861 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005862
Daniel Veillardc0826a72004-08-10 14:17:33 +00005863 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005864 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005865 if (attr == NULL) {
5866 xmlSchemaPMissingAttrErr(ctxt,
5867 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005868 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 "name", NULL);
5870 return (NULL);
5871 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005872 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005873 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00005874 return (NULL);
5875 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005876 }
5877
5878 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005879 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880
Daniel Veillard01fa6152004-06-29 17:04:39 +00005881 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00005883 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005884 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005885 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005886 if (type == NULL)
5887 return (NULL);
5888 type->node = node;
5889 type->type = XML_SCHEMA_TYPE_SIMPLE;
5890 /*
5891 * Check for illegal attributes.
5892 */
5893 attr = node->properties;
5894 while (attr != NULL) {
5895 if (attr->ns == NULL) {
5896 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
5897 xmlSchemaPIllegalAttrErr(ctxt,
5898 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005899 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005900 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005901 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5902 xmlSchemaPIllegalAttrErr(ctxt,
5903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005904 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 }
5906 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005907 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005908 } else {
5909 /*
5910 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005911 *
5912 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005914 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005915 if (type == NULL)
5916 return (NULL);
5917 type->node = node;
5918 type->type = XML_SCHEMA_TYPE_SIMPLE;
5919 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
5920 /*
5921 * Check for illegal attributes.
5922 */
5923 attr = node->properties;
5924 while (attr != NULL) {
5925 if (attr->ns == NULL) {
5926 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5927 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005928 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005929 xmlSchemaPIllegalAttrErr(ctxt,
5930 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005931 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005932 }
5933 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5934 xmlSchemaPIllegalAttrErr(ctxt,
5935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005936 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005937 }
5938 attr = attr->next;
5939 }
5940 /*
5941 * Attribute "final".
5942 */
5943 attr = xmlSchemaGetPropNode(node, "final");
5944 if (attr == NULL) {
5945 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
5946 } else {
5947 attrValue = xmlSchemaGetProp(ctxt, node, "final");
5948 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
5949 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
5950 XML_SCHEMAS_TYPE_FINAL_LIST,
5951 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
5952
5953 xmlSchemaPSimpleTypeErr(ctxt,
5954 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005955 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005956 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005957 attrValue, NULL, NULL, NULL);
5958 }
5959 }
5960 }
5961 /* TODO: Check id. */
5962 type->id = xmlSchemaGetProp(ctxt, node, "id");
5963 /*
5964 * And now for the children...
5965 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005966 oldCtxtType = ctxt->ctxtType;
5967 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005968 ctxt->ctxtType = type;
5969 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00005970 child = node->children;
5971 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005972 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5973 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005974 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005975 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00005976 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005977 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00005978 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005979 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 subtype = (xmlSchemaTypePtr)
5982 xmlSchemaParseList(ctxt, schema, child);
5983 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005985 subtype = (xmlSchemaTypePtr)
5986 xmlSchemaParseUnion(ctxt, schema, child);
5987 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005988 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005989 type->subtypes = subtype;
5990 if ((child != NULL) || (subtype == NULL)) {
5991 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005992 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005993 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00005994 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005995 ctxt->parentItem = oldParentItem;
5996 ctxt->ctxtType = oldCtxtType;
5997 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005998
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 return (type);
6000}
6001
6002
6003/**
6004 * xmlSchemaParseGroup:
6005 * @ctxt: a schema validation context
6006 * @schema: the schema being built
6007 * @node: a subtree containing XML Schema informations
6008 *
6009 * parse a XML schema Group definition
6010 * *WARNING* this interface is highly subject to change
6011 *
William M. Bracke7091952004-05-11 15:09:58 +00006012 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006013 * 1 in case of success.
6014 */
6015static xmlSchemaTypePtr
6016xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006017 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006018{
6019 xmlSchemaTypePtr type, subtype;
6020 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006021 const xmlChar *name;
6022 const xmlChar *ref = NULL, *refNs = NULL;
6023 char buf[100];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006024 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006025
6026 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6027 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006028 /*
6029 * TODO: Validate the element even if no item is created
6030 * (i.e. min/maxOccurs == 0).
6031 */
6032 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6033 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6034 if ((minOccurs == 0) && (maxOccurs == 0)) {
6035 return (NULL);
6036 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006037 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006038 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006039 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6040 if (ref == NULL) {
6041 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006042 XML_SCHEMAP_GROUP_NONAME_NOREF,
6043 "Group definition or particle: One of the attributes \"name\" "
6044 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006045 return (NULL);
6046 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006047 if (refNs == NULL)
6048 refNs = schema->targetNamespace;
6049 snprintf(buf, 99, "anongroup %d", ctxt->counter++ + 1);
6050 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006052 type = xmlSchemaAddGroup(ctxt, schema, name, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 if (type == NULL)
6054 return (NULL);
6055 type->node = node;
6056 type->type = XML_SCHEMA_TYPE_GROUP;
Daniel Veillard3646d642004-06-02 19:19:14 +00006057 if (topLevel)
6058 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006059 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006060 type->ref = ref;
6061 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006062 type->minOccurs = minOccurs;
6063 type->maxOccurs = maxOccurs;
6064 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006065 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006066
6067 child = node->children;
6068 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006069 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6070 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 }
6072 subtype = NULL;
6073 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006074 subtype = (xmlSchemaTypePtr)
6075 xmlSchemaParseAll(ctxt, schema, child);
6076 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006077 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006078 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006080 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006081 subtype = (xmlSchemaTypePtr)
6082 xmlSchemaParseSequence(ctxt, schema, child);
6083 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006084 }
6085 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006086 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006088 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006089 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006090 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006091 }
6092
6093 return (type);
6094}
6095
6096/**
6097 * xmlSchemaParseAll:
6098 * @ctxt: a schema validation context
6099 * @schema: the schema being built
6100 * @node: a subtree containing XML Schema informations
6101 *
6102 * parse a XML schema All definition
6103 * *WARNING* this interface is highly subject to change
6104 *
William M. Bracke7091952004-05-11 15:09:58 +00006105 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 * 1 in case of success.
6107 */
6108static xmlSchemaTypePtr
6109xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006110 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006111{
6112 xmlSchemaTypePtr type, subtype, last = NULL;
6113 xmlNodePtr child = NULL;
6114 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006115 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006116
6117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6118 return (NULL);
6119
6120
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006121 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006122 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006123 if (type == NULL)
6124 return (NULL);
6125 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00006126 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006127 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006128
6129 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
6130 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006131
6132 oldcontainer = ctxt->container;
6133 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006134 child = node->children;
6135 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006136 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6137 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 }
6139 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 subtype = (xmlSchemaTypePtr)
6141 xmlSchemaParseElement(ctxt, schema, child, 0);
6142 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00006143 if (subtype->minOccurs > 1)
6144 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006145 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006146 NULL, NULL);
6147 if (subtype->maxOccurs > 1)
6148 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006149 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00006150 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006151 if (last == NULL) {
6152 type->subtypes = subtype;
6153 last = subtype;
6154 } else {
6155 last->next = subtype;
6156 last = subtype;
6157 }
6158 last->next = NULL;
6159 }
6160 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006161 }
6162 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006163 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006164 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006165 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006166 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006167 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006168 return (type);
6169}
6170
6171/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006172 * xmlSchemaCleanupDoc:
6173 * @ctxt: a schema validation context
6174 * @node: the root of the document.
6175 *
6176 * removes unwanted nodes in a schemas document tree
6177 */
6178static void
6179xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
6180{
6181 xmlNodePtr delete, cur;
6182
6183 if ((ctxt == NULL) || (root == NULL)) return;
6184
6185 /*
6186 * Remove all the blank text nodes
6187 */
6188 delete = NULL;
6189 cur = root;
6190 while (cur != NULL) {
6191 if (delete != NULL) {
6192 xmlUnlinkNode(delete);
6193 xmlFreeNode(delete);
6194 delete = NULL;
6195 }
6196 if (cur->type == XML_TEXT_NODE) {
6197 if (IS_BLANK_NODE(cur)) {
6198 if (xmlNodeGetSpacePreserve(cur) != 1) {
6199 delete = cur;
6200 }
6201 }
6202 } else if ((cur->type != XML_ELEMENT_NODE) &&
6203 (cur->type != XML_CDATA_SECTION_NODE)) {
6204 delete = cur;
6205 goto skip_children;
6206 }
6207
6208 /*
6209 * Skip to next node
6210 */
6211 if (cur->children != NULL) {
6212 if ((cur->children->type != XML_ENTITY_DECL) &&
6213 (cur->children->type != XML_ENTITY_REF_NODE) &&
6214 (cur->children->type != XML_ENTITY_NODE)) {
6215 cur = cur->children;
6216 continue;
6217 }
6218 }
6219 skip_children:
6220 if (cur->next != NULL) {
6221 cur = cur->next;
6222 continue;
6223 }
6224
6225 do {
6226 cur = cur->parent;
6227 if (cur == NULL)
6228 break;
6229 if (cur == root) {
6230 cur = NULL;
6231 break;
6232 }
6233 if (cur->next != NULL) {
6234 cur = cur->next;
6235 break;
6236 }
6237 } while (cur != NULL);
6238 }
6239 if (delete != NULL) {
6240 xmlUnlinkNode(delete);
6241 xmlFreeNode(delete);
6242 delete = NULL;
6243 }
6244}
6245
William M. Brack2f2a6632004-08-20 23:09:47 +00006246
6247/**
6248 * xmlSchemaImportSchema
6249 *
6250 * @ctxt: a schema validation context
6251 * @schemaLocation: an URI defining where to find the imported schema
6252 *
6253 * import a XML schema
6254 * *WARNING* this interface is highly subject to change
6255 *
6256 * Returns -1 in case of error and 1 in case of success.
6257 */
6258#if 0
6259static xmlSchemaImportPtr
6260xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
6261 const xmlChar *schemaLocation)
6262{
6263 xmlSchemaImportPtr import;
6264 xmlSchemaParserCtxtPtr newctxt;
6265
6266 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
6267 if (newctxt == NULL) {
6268 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
6269 NULL);
6270 return (NULL);
6271 }
6272 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
6273 /* Keep the same dictionnary for parsing, really */
6274 xmlDictReference(ctxt->dict);
6275 newctxt->dict = ctxt->dict;
6276 newctxt->includes = 0;
6277 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
6278
6279 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
6280 ctxt->userData);
6281
6282 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6283 if (import == NULL) {
6284 xmlSchemaPErrMemory(NULL, "allocating imported schema",
6285 NULL);
6286 xmlSchemaFreeParserCtxt(newctxt);
6287 return (NULL);
6288 }
6289
6290 memset(import, 0, sizeof(xmlSchemaImport));
6291 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
6292 import->schema = xmlSchemaParse(newctxt);
6293
6294 if (import->schema == NULL) {
6295 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00006296 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00006297 "Failed to import schema from location \"%s\".\n",
6298 schemaLocation, NULL);
6299
6300 xmlSchemaFreeParserCtxt(newctxt);
6301 /* The schemaLocation is held by the dictionary.
6302 if (import->schemaLocation != NULL)
6303 xmlFree((xmlChar *)import->schemaLocation);
6304 */
6305 xmlFree(import);
6306 return NULL;
6307 }
6308
6309 xmlSchemaFreeParserCtxt(newctxt);
6310 return import;
6311}
6312#endif
6313
6314static void
6315xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
6316{
6317 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6318 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
6319
6320 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6321 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
6322
6323 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
6324 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
6325 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
6326 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
6327 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
6328 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
6329 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
6330 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
6331
6332 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
6333 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
6334 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
6335 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
6336 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
6337 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
6338}
6339
6340static void
6341xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
6342 xmlSchemaPtr schema,
6343 xmlNodePtr node)
6344{
6345 xmlAttrPtr attr;
6346 const xmlChar *val;
6347
6348 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
6349 if (attr != NULL) {
6350 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6351 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6352 XML_SCHEMAS_QUALIF_ELEM) != 0) {
6353 xmlSchemaPSimpleTypeErr(ctxt,
6354 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
6355 NULL, NULL, (xmlNodePtr) attr, NULL,
6356 "(qualified | unqualified)", val, NULL, NULL, NULL);
6357 }
6358 }
6359
6360 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
6361 if (attr != NULL) {
6362 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6363 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
6364 XML_SCHEMAS_QUALIF_ATTR) != 0) {
6365 xmlSchemaPSimpleTypeErr(ctxt,
6366 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
6367 NULL, NULL, (xmlNodePtr) attr, NULL,
6368 "(qualified | unqualified)", val, NULL, NULL, NULL);
6369 }
6370 }
6371
6372 attr = xmlSchemaGetPropNode(node, "finalDefault");
6373 if (attr != NULL) {
6374 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6375 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6376 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
6377 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
6378 -1,
6379 XML_SCHEMAS_FINAL_DEFAULT_LIST,
6380 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
6381 xmlSchemaPSimpleTypeErr(ctxt,
6382 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6383 NULL, NULL, (xmlNodePtr) attr, NULL,
6384 "(#all | List of (extension | restriction | list | union))",
6385 val, NULL, NULL, NULL);
6386 }
6387 }
6388
6389 attr = xmlSchemaGetPropNode(node, "blockDefault");
6390 if (attr != NULL) {
6391 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6392 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
6393 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
6394 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
6395 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
6396 xmlSchemaPSimpleTypeErr(ctxt,
6397 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6398 NULL, NULL, (xmlNodePtr) attr, NULL,
6399 "(#all | List of (extension | restriction | substitution))",
6400 val, NULL, NULL, NULL);
6401 }
6402 }
6403}
6404
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006405/**
6406 * xmlSchemaParseSchemaTopLevel:
6407 * @ctxt: a schema validation context
6408 * @schema: the schemas
6409 * @nodes: the list of top level nodes
6410 *
6411 * Returns the internal XML Schema structure built from the resource or
6412 * NULL in case of error
6413 */
6414static void
6415xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
6416 xmlSchemaPtr schema, xmlNodePtr nodes)
6417{
6418 xmlNodePtr child;
6419 xmlSchemaAnnotPtr annot;
6420
6421 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
6422 return;
6423
6424 child = nodes;
6425 while ((IS_SCHEMA(child, "include")) ||
6426 (IS_SCHEMA(child, "import")) ||
6427 (IS_SCHEMA(child, "redefine")) ||
6428 (IS_SCHEMA(child, "annotation"))) {
6429 if (IS_SCHEMA(child, "annotation")) {
6430 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6431 if (schema->annot == NULL)
6432 schema->annot = annot;
6433 else
6434 xmlSchemaFreeAnnot(annot);
6435 } else if (IS_SCHEMA(child, "import")) {
6436 xmlSchemaParseImport(ctxt, schema, child);
6437 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006438 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006439 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00006440 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006441 } else if (IS_SCHEMA(child, "redefine")) {
6442 TODO
6443 }
6444 child = child->next;
6445 }
6446 while (child != NULL) {
6447 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006448 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006449 child = child->next;
6450 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006451 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006452 child = child->next;
6453 } else if (IS_SCHEMA(child, "element")) {
6454 xmlSchemaParseElement(ctxt, schema, child, 1);
6455 child = child->next;
6456 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00006457 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006458 child = child->next;
6459 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006460 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006461 child = child->next;
6462 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00006463 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006464 child = child->next;
6465 } else if (IS_SCHEMA(child, "notation")) {
6466 xmlSchemaParseNotation(ctxt, schema, child);
6467 child = child->next;
6468 } else {
6469 xmlSchemaPErr2(ctxt, NULL, child,
6470 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006472 child->name, NULL);
6473 child = child->next;
6474 }
6475 while (IS_SCHEMA(child, "annotation")) {
6476 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6477 if (schema->annot == NULL)
6478 schema->annot = annot;
6479 else
6480 xmlSchemaFreeAnnot(annot);
6481 child = child->next;
6482 }
6483 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006484 ctxt->parentItem = NULL;
6485 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006486}
6487
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006488static xmlSchemaImportPtr
6489xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
6490 xmlHashTablePtr *imports,
6491 const xmlChar *nsName)
6492{
6493 xmlSchemaImportPtr ret;
6494
6495 if (*imports == NULL) {
6496 *imports = xmlHashCreate(10);
6497 if (*imports == NULL) {
6498 xmlSchemaPCustomErr(ctxt,
6499 XML_SCHEMAP_FAILED_BUILD_IMPORT,
6500 NULL, NULL, (xmlNodePtr) ctxt->doc,
6501 "Internal error: failed to build the import table",
6502 NULL);
6503 return (NULL);
6504 }
6505 }
6506 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
6507 if (ret == NULL) {
6508 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
6509 return (NULL);
6510 }
6511 memset(ret, 0, sizeof(xmlSchemaImport));
6512 if (nsName == NULL)
6513 nsName = XML_SCHEMAS_NO_NAMESPACE;
6514 xmlHashAddEntry(*imports, nsName, ret);
6515
6516 return (ret);
6517}
6518
6519static int
6520xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006521 xmlSchemaPtr schema,
6522 xmlNodePtr node,
6523 const xmlChar *nsName,
6524 const xmlChar *location,
6525 xmlDocPtr *doc,
6526 const xmlChar **targetNamespace,
6527 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006528{
6529 xmlParserCtxtPtr parserCtxt;
6530 xmlSchemaImportPtr import;
6531 const xmlChar *ns;
6532 xmlNodePtr root;
6533
6534 /*
6535 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
6536 * <xsi:noNamespaceSchemaLocation>.
6537 */
6538 *doc = NULL;
6539 /*
6540 * Given that the schemaLocation [attribute] is only a hint, it is open
6541 * to applications to ignore all but the first <import> for a given
6542 * namespace, regardless of the ·actual value· of schemaLocation, but
6543 * such a strategy risks missing useful information when new
6544 * schemaLocations are offered.
6545 *
6546 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
6547 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
6548 * valid or not.
6549 * We will follow XSV here.
6550 */
6551 if (location == NULL) {
6552 /*
6553 * Schema Document Location Strategy:
6554 *
6555 * 3 Based on the namespace name, identify an existing schema document,
6556 * either as a resource which is an XML document or a <schema> element
6557 * information item, in some local schema repository;
6558 *
6559 * 5 Attempt to resolve the namespace name to locate such a resource.
6560 *
6561 * NOTE: Those stategies are not supported, so we will skip.
6562 */
6563 return (0);
6564 }
6565 if (nsName == NULL)
6566 ns = XML_SCHEMAS_NO_NAMESPACE;
6567 else
6568 ns = nsName;
6569
6570 import = xmlHashLookup(schema->schemasImports, ns);
6571 if (import != NULL) {
6572 /*
6573 * There was a valid resource for the specified namespace already
6574 * defined, so skip.
6575 * TODO: This might be changed someday to allow import of
6576 * components from multiple documents for a single target namespace.
6577 */
6578 return (0);
6579 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006581 /*
6582 * Schema Document Location Strategy:
6583 *
6584 * 2 Based on the location URI, identify an existing schema document,
6585 * either as a resource which is an XML document or a <schema> element
6586 * information item, in some local schema repository;
6587 *
6588 * 4 Attempt to resolve the location URI, to locate a resource on the
6589 * web which is or contains or references a <schema> element;
6590 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
6591 *
6592 */
6593 if ((absolute == 0) && (node != NULL)) {
6594 xmlChar *base, *URI;
6595
6596 base = xmlNodeGetBase(node->doc, node);
6597 if (base == NULL) {
6598 URI = xmlBuildURI(location, node->doc->URL);
6599 } else {
6600 URI = xmlBuildURI(location, base);
6601 xmlFree(base);
6602 }
6603 if (URI != NULL) {
6604 location = xmlDictLookup(ctxt->dict, URI, -1);
6605 xmlFree(URI);
6606 }
6607 }
6608 parserCtxt = xmlNewParserCtxt();
6609 if (parserCtxt == NULL) {
6610 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
6611 "allocating a parser context", NULL);
6612 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00006613 }
6614
6615 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
6616 xmlDictFree(parserCtxt->dict);
6617 parserCtxt->dict = ctxt->dict;
6618 xmlDictReference(parserCtxt->dict);
6619 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006620
6621 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
6622 NULL, SCHEMAS_PARSE_OPTIONS);
6623
6624 /*
6625 * 2.1 The referent is (a fragment of) a resource which is an
6626 * XML document (see clause 1.1), which in turn corresponds to
6627 * a <schema> element information item in a well-formed information
6628 * set, which in turn corresponds to a valid schema.
6629 * TODO: What to do with the "fragment" stuff?
6630 *
6631 * 2.2 The referent is a <schema> element information item in
6632 * a well-formed information set, which in turn corresponds
6633 * to a valid schema.
6634 * NOTE: 2.2 won't apply, since only XML documents will be processed
6635 * here.
6636 */
6637 if (*doc == NULL) {
6638 xmlErrorPtr lerr;
6639 /*
6640 * It is *not* an error for the application schema reference
6641 * strategy to fail.
6642 *
6643 * If the doc is NULL and the parser error is an IO error we
6644 * will assume that the resource could not be located or accessed.
6645 *
6646 * TODO: Try to find specific error codes to react only on
6647 * localisation failures.
6648 *
6649 * TODO, FIXME: Check the spec: is a namespace added to the imported
6650 * namespaces, even if the schemaLocation did not provide
6651 * a resource? I guess so, since omitting the "schemaLocation"
6652 * attribute, imports a namespace as well.
6653 */
6654 lerr = xmlGetLastError();
6655 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
6656 xmlFreeParserCtxt(parserCtxt);
6657 return(0);
6658 }
6659
6660 xmlSchemaPCustomErr(ctxt,
6661 XML_SCHEMAP_SRC_IMPORT_2_1,
6662 NULL, NULL, node,
6663 "Failed to parse the resource '%s' for import",
6664 location);
6665 xmlFreeParserCtxt(parserCtxt);
6666 return(XML_SCHEMAP_SRC_IMPORT_2_1);
6667 }
6668 xmlFreeParserCtxt(parserCtxt);
6669
6670 root = xmlDocGetRootElement(*doc);
6671 if (root == NULL) {
6672 xmlSchemaPCustomErr(ctxt,
6673 XML_SCHEMAP_SRC_IMPORT_2_1,
6674 NULL, NULL, node,
6675 "The XML document '%s' to be imported has no document "
6676 "element", location);
6677 xmlFreeDoc(*doc);
6678 *doc = NULL;
6679 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6680 }
6681
6682 xmlSchemaCleanupDoc(ctxt, root);
6683
6684 if (!IS_SCHEMA(root, "schema")) {
6685 xmlSchemaPCustomErr(ctxt,
6686 XML_SCHEMAP_SRC_IMPORT_2_1,
6687 NULL, NULL, node,
6688 "The XML document '%s' to be imported is not a XML schema document",
6689 location);
6690 xmlFreeDoc(*doc);
6691 *doc = NULL;
6692 return (XML_SCHEMAP_SRC_IMPORT_2_1);
6693 }
6694 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
6695 /*
6696 * Schema Representation Constraint: Import Constraints and Semantics
6697 */
6698 if (nsName == NULL) {
6699 if (*targetNamespace != NULL) {
6700 xmlSchemaPCustomErr(ctxt,
6701 XML_SCHEMAP_SRC_IMPORT_3_2,
6702 NULL, NULL, node,
6703 "The XML schema to be imported is not expected "
6704 "to have a target namespace; this differs from "
6705 "its target namespace of '%s'", *targetNamespace);
6706 xmlFreeDoc(*doc);
6707 *doc = NULL;
6708 return (XML_SCHEMAP_SRC_IMPORT_3_2);
6709 }
6710 } else {
6711 if (*targetNamespace == NULL) {
6712 xmlSchemaPCustomErr(ctxt,
6713 XML_SCHEMAP_SRC_IMPORT_3_1,
6714 NULL, NULL, node,
6715 "The XML schema to be imported is expected to have a target "
6716 "namespace of '%s'", nsName);
6717 xmlFreeDoc(*doc);
6718 *doc = NULL;
6719 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6720 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
6721 xmlSchemaPCustomErrExt(ctxt,
6722 XML_SCHEMAP_SRC_IMPORT_3_1,
6723 NULL, NULL, node,
6724 "The XML schema to be imported is expected to have a "
6725 "target namespace of '%s'; this differs from "
6726 "its target namespace of '%s'",
6727 nsName, *targetNamespace, NULL);
6728 xmlFreeDoc(*doc);
6729 *doc = NULL;
6730 return (XML_SCHEMAP_SRC_IMPORT_3_1);
6731 }
6732 }
6733
6734 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
6735 if (import == NULL) {
6736 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
6737 NULL, NULL, NULL,
6738 "Internal error: xmlSchemaAcquireSchemaDoc, "
6739 "failed to build import table", NULL);
6740 xmlFreeDoc(*doc);
6741 *doc = NULL;
6742 return (-1);
6743 }
6744 import->schemaLocation = location;
6745 import->doc = *doc;
6746 return (0);
6747}
William M. Brack2f2a6632004-08-20 23:09:47 +00006748
6749/**
6750 * xmlSchemaParseImport:
6751 * @ctxt: a schema validation context
6752 * @schema: the schema being built
6753 * @node: a subtree containing XML Schema informations
6754 *
6755 * parse a XML schema Import definition
6756 * *WARNING* this interface is highly subject to change
6757 *
6758 * Returns 0 in case of success, a positive error code if
6759 * not valid and -1 in case of an internal error.
6760 */
6761static int
6762xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6763 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006764{
6765 xmlNodePtr child;
6766 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006767 const xmlChar *schemaLocation = NULL;
6768 const xmlChar *targetNamespace, *oldTNS, *url;
6769 xmlAttrPtr attr;
6770 xmlDocPtr doc;
6771 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006772 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006773
6774
6775 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6776 return (-1);
6777
6778 /*
6779 * Check for illegal attributes.
6780 */
6781 attr = node->properties;
6782 while (attr != NULL) {
6783 if (attr->ns == NULL) {
6784 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6785 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6786 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6787 xmlSchemaPIllegalAttrErr(ctxt,
6788 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6789 NULL, NULL, attr);
6790 }
6791 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6792 xmlSchemaPIllegalAttrErr(ctxt,
6793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6794 NULL, NULL, attr);
6795 }
6796 attr = attr->next;
6797 }
6798 /*
6799 * Extract and validate attributes.
6800 */
6801 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6802 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6803 &namespace) != 0) {
6804 xmlSchemaPSimpleTypeErr(ctxt,
6805 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
6806 NULL, NULL, node,
6807 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6808 NULL, namespace, NULL, NULL, NULL);
6809 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
6810 }
6811
6812 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
6813 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6814 &schemaLocation) != 0) {
6815 xmlSchemaPSimpleTypeErr(ctxt,
6816 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
6817 NULL, NULL, node,
6818 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
6819 NULL, namespace, NULL, NULL, NULL);
6820 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
6821 }
6822 /*
6823 * And now for the children...
6824 */
6825 child = node->children;
6826 if (IS_SCHEMA(child, "annotation")) {
6827 /*
6828 * the annotation here is simply discarded ...
6829 */
6830 child = child->next;
6831 }
6832 if (child != NULL) {
6833 xmlSchemaPContentErr(ctxt,
6834 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
6835 NULL, NULL, node, child, NULL,
6836 "(annotation?)");
6837 }
6838 /*
6839 * Apply additional constraints.
6840 */
6841 if (namespace != NULL) {
6842 /*
6843 * 1.1 If the namespace [attribute] is present, then its ·actual value·
6844 * must not match the ·actual value· of the enclosing <schema>'s
6845 * targetNamespace [attribute].
6846 */
6847 if (xmlStrEqual(schema->targetNamespace, namespace)) {
6848 xmlSchemaPCustomErr(ctxt,
6849 XML_SCHEMAP_SRC_IMPORT_1_1,
6850 NULL, NULL, node,
6851 "The value of the attribute 'namespace' must not match "
6852 "the target namespace '%s' of the importing schema",
6853 schema->targetNamespace);
6854 return (XML_SCHEMAP_SRC_IMPORT_1_1);
6855 }
6856 } else {
6857 /*
6858 * 1.2 If the namespace [attribute] is not present, then the enclosing
6859 * <schema> must have a targetNamespace [attribute].
6860 */
6861 if (schema->targetNamespace == NULL) {
6862 xmlSchemaPCustomErr(ctxt,
6863 XML_SCHEMAP_SRC_IMPORT_1_2,
6864 NULL, NULL, node,
6865 "The attribute 'namespace' must be existent if "
6866 "the importing schema has no target namespace",
6867 NULL);
6868 return (XML_SCHEMAP_SRC_IMPORT_1_2);
6869 }
6870 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006871 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006872 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00006873 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006874 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
6875 schemaLocation, &doc, &targetNamespace, 0);
6876 if (ret != 0) {
6877 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00006878 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006879 return (ret);
6880 } else if (doc != NULL) {
6881 /*
6882 * Save and reset the context & schema.
6883 */
6884 url = ctxt->URL;
6885 /* TODO: Is using the doc->URL here correct? */
6886 ctxt->URL = doc->URL;
6887 flags = schema->flags;
6888 oldTNS = schema->targetNamespace;
6889 /*
6890 * Parse the schema.
6891 */
6892 root = xmlDocGetRootElement(doc);
6893 xmlSchemaClearSchemaDefaults(schema);
6894 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
6895 schema->targetNamespace = targetNamespace;
6896 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
6897 /*
6898 * Restore the context & schema.
6899 */
6900 schema->flags = flags;
6901 schema->targetNamespace = oldTNS;
6902 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00006903 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006904
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006905 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00006906}
6907
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006908/**
6909 * xmlSchemaParseInclude:
6910 * @ctxt: a schema validation context
6911 * @schema: the schema being built
6912 * @node: a subtree containing XML Schema informations
6913 *
6914 * parse a XML schema Include definition
6915 *
William M. Bracke7091952004-05-11 15:09:58 +00006916 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006917 * 1 in case of success.
6918 */
6919static int
6920xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6921 xmlNodePtr node)
6922{
6923 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006924 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006925 xmlDocPtr doc;
6926 xmlNodePtr root;
6927 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006928 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00006929 xmlAttrPtr attr;
6930 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00006931 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006932
6933
6934 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6935 return (-1);
6936
6937 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00006938 * Check for illegal attributes.
6939 */
6940 attr = node->properties;
6941 while (attr != NULL) {
6942 if (attr->ns == NULL) {
6943 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6944 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
6945 xmlSchemaPIllegalAttrErr(ctxt,
6946 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6947 NULL, NULL, attr);
6948 }
6949 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6950 xmlSchemaPIllegalAttrErr(ctxt,
6951 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6952 NULL, NULL, attr);
6953 }
6954 attr = attr->next;
6955 }
6956 /*
6957 * Extract and validate attributes.
6958 */
6959 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006960 * Preliminary step, extract the URI-Reference for the include and
6961 * make an URI from the base.
6962 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006963 attr = xmlSchemaGetPropNode(node, "schemaLocation");
6964 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006965 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006966 xmlChar *uri = NULL;
6967
6968 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
6969 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
6970 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006971 base = xmlNodeGetBase(node->doc, node);
6972 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006973 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006974 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006975 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006976 xmlFree(base);
6977 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006978 if (uri != NULL) {
6979 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
6980 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006981 }
6982 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00006983 xmlSchemaPMissingAttrErr(ctxt,
6984 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
6985 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006986 return (-1);
6987 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006988 /*
6989 * And now for the children...
6990 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00006991 child = node->children;
6992 while (IS_SCHEMA(child, "annotation")) {
6993 /*
6994 * the annotations here are simply discarded ...
6995 */
6996 child = child->next;
6997 }
6998 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006999 xmlSchemaPContentErr(ctxt,
7000 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7001 NULL, NULL, node, child, NULL,
7002 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007003 }
7004
7005 /*
7006 * First step is to parse the input document into an DOM/Infoset
7007 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007008 /*
7009 * TODO: Use xmlCtxtReadFile to share the dictionary.
7010 */
7011 parserCtxt = xmlNewParserCtxt();
7012 if (parserCtxt == NULL) {
7013 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7014 "allocating a parser context", NULL);
7015 return(-1);
7016 }
7017
7018 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7019 xmlDictFree(parserCtxt->dict);
7020 parserCtxt->dict = ctxt->dict;
7021 xmlDictReference(parserCtxt->dict);
7022 }
7023
7024 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7025 NULL, SCHEMAS_PARSE_OPTIONS);
7026 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007027 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007028 /*
7029 * TODO: It is not an error for the ·actual value· of the
7030 * schemaLocation [attribute] to fail to resolve it all, in which
7031 * case no corresponding inclusion is performed.
7032 * So do we need a warning report here?
7033 */
7034 xmlSchemaPCustomErr(ctxt,
7035 XML_SCHEMAP_FAILED_LOAD,
7036 NULL, NULL, node,
7037 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007038 return(-1);
7039 }
7040
7041 /*
7042 * Then extract the root of the schema
7043 */
7044 root = xmlDocGetRootElement(doc);
7045 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007046 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007047 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007048 NULL, NULL, node,
7049 "The included document '%s' has no document "
7050 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007051 xmlFreeDoc(doc);
7052 return (-1);
7053 }
7054
7055 /*
7056 * Remove all the blank text nodes
7057 */
7058 xmlSchemaCleanupDoc(ctxt, root);
7059
7060 /*
7061 * Check the schemas top level element
7062 */
7063 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007064 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007065 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007066 NULL, NULL, node,
7067 "The document '%s' to be included is not a schema document",
7068 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007069 xmlFreeDoc(doc);
7070 return (-1);
7071 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007072
William M. Brack2f2a6632004-08-20 23:09:47 +00007073 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007074 /*
7075 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7076 * value· is identical to the ·actual value· of the targetNamespace
7077 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7078 */
7079 if (targetNamespace != NULL) {
7080 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007081 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007082 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007083 NULL, NULL, node,
7084 "The target namespace of the included schema "
7085 "'%s' has to be absent, since the including schema "
7086 "has no target namespace",
7087 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007088 xmlFreeDoc(doc);
7089 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007090 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7091 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007092 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007093 NULL, NULL, node,
7094 "The target namespace '%s' of the included schema '%s' "
7095 "differs from '%s' of the including schema",
7096 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007097 xmlFreeDoc(doc);
7098 return (-1);
7099 }
7100 } else if (schema->targetNamespace != NULL) {
7101 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7102 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7103 } else
7104 wasConvertingNs = 1;
7105 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007106 /*
7107 * register the include
7108 */
7109 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7110 if (include == NULL) {
7111 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7112 xmlFreeDoc(doc);
7113 return (-1);
7114 }
7115
7116 memset(include, 0, sizeof(xmlSchemaInclude));
7117 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7118 include->doc = doc;
7119 include->next = schema->includes;
7120 schema->includes = include;
7121
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007122 /*
7123 * parse the declarations in the included file like if they
7124 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007125 */
7126 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007127 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007128 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007129 /*
7130 * The default values ("blockDefault", "elementFormDefault", etc.)
7131 * are set to the values of the included schema and restored afterwards.
7132 */
7133 saveFlags = schema->flags;
7134 xmlSchemaClearSchemaDefaults(schema);
7135 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007136 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00007137 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007138 /*
7139 * Remove the converting flag.
7140 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007141 if ((wasConvertingNs == 0) &&
7142 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00007143 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007144 return (1);
7145}
7146
7147/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007148 * xmlSchemaParseChoice:
7149 * @ctxt: a schema validation context
7150 * @schema: the schema being built
7151 * @node: a subtree containing XML Schema informations
7152 *
7153 * parse a XML schema Choice definition
7154 * *WARNING* this interface is highly subject to change
7155 *
William M. Bracke7091952004-05-11 15:09:58 +00007156 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007157 * 1 in case of success.
7158 */
7159static xmlSchemaTypePtr
7160xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007161 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007162{
7163 xmlSchemaTypePtr type, subtype, last = NULL;
7164 xmlNodePtr child = NULL;
7165 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007166 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007167 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007168
7169 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7170 return (NULL);
7171
7172
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007173 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007174 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007175 if (type == NULL)
7176 return (NULL);
7177 type->node = node;
7178 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007179 /*
7180 * Check for illegal attributes.
7181 */
7182 attr = node->properties;
7183 while (attr != NULL) {
7184 if (attr->ns == NULL) {
7185 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7186 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7187 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7188 xmlSchemaPIllegalAttrErr(ctxt,
7189 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7190 NULL, type, attr);
7191 }
7192 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7193 xmlSchemaPIllegalAttrErr(ctxt,
7194 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7195 NULL, type, attr);
7196 }
7197 attr = attr->next;
7198 }
7199 /*
7200 * Extract and validate attributes.
7201 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007202 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007203 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7204 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7205 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007206 /*
7207 * And now for the children...
7208 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007209 oldcontainer = ctxt->container;
7210 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007211 child = node->children;
7212 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007213 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7214 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007215 }
7216 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007217 (IS_SCHEMA(child, "group")) ||
7218 (IS_SCHEMA(child, "any")) ||
7219 (IS_SCHEMA(child, "choice")) ||
7220 (IS_SCHEMA(child, "sequence"))) {
7221 subtype = NULL;
7222 if (IS_SCHEMA(child, "element")) {
7223 subtype = (xmlSchemaTypePtr)
7224 xmlSchemaParseElement(ctxt, schema, child, 0);
7225 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007226 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007227 } else if (IS_SCHEMA(child, "any")) {
7228 subtype = xmlSchemaParseAny(ctxt, schema, child);
7229 } else if (IS_SCHEMA(child, "sequence")) {
7230 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7231 } else if (IS_SCHEMA(child, "choice")) {
7232 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7233 }
7234 if (subtype != NULL) {
7235 if (last == NULL) {
7236 type->subtypes = subtype;
7237 last = subtype;
7238 } else {
7239 last->next = subtype;
7240 last = subtype;
7241 }
7242 last->next = NULL;
7243 }
7244 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007245 }
7246 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007247 /* TODO: error code. */
7248 xmlSchemaPContentErr(ctxt,
7249 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
7250 NULL, type, node, child, NULL,
7251 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007252 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007253 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007254 return (type);
7255}
7256
7257/**
7258 * xmlSchemaParseSequence:
7259 * @ctxt: a schema validation context
7260 * @schema: the schema being built
7261 * @node: a subtree containing XML Schema informations
7262 *
7263 * parse a XML schema Sequence definition
7264 * *WARNING* this interface is highly subject to change
7265 *
William M. Bracke7091952004-05-11 15:09:58 +00007266 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007267 * 1 in case of success.
7268 */
7269static xmlSchemaTypePtr
7270xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007271 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007272{
7273 xmlSchemaTypePtr type, subtype, last = NULL;
7274 xmlNodePtr child = NULL;
7275 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007276 xmlAttrPtr attr;
7277 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007278
7279 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7280 return (NULL);
7281
William M. Brack2f2a6632004-08-20 23:09:47 +00007282 oldcontainer = ctxt->container;
7283 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
7284 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007285 if (type == NULL)
7286 return (NULL);
7287 type->node = node;
7288 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00007289 /*
7290 * Check for illegal attributes.
7291 */
7292 attr = node->properties;
7293 while (attr != NULL) {
7294 if (attr->ns == NULL) {
7295 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7296 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7297 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
7298 xmlSchemaPIllegalAttrErr(ctxt,
7299 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7300 NULL, type, attr);
7301 }
7302 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7303 xmlSchemaPIllegalAttrErr(ctxt,
7304 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7305 NULL, type, attr);
7306 }
7307 attr = attr->next;
7308 }
7309 /*
7310 * Extract and validate attributes.
7311 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007312 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007313 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7314 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7315 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00007316 /*
7317 * And now for the children...
7318 */
7319 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007320 child = node->children;
7321 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007322 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7323 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007324 }
7325 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007326 (IS_SCHEMA(child, "group")) ||
7327 (IS_SCHEMA(child, "any")) ||
7328 (IS_SCHEMA(child, "choice")) ||
7329 (IS_SCHEMA(child, "sequence"))) {
7330 subtype = NULL;
7331 if (IS_SCHEMA(child, "element")) {
7332 subtype = (xmlSchemaTypePtr)
7333 xmlSchemaParseElement(ctxt, schema, child, 0);
7334 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007335 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007336 } else if (IS_SCHEMA(child, "any")) {
7337 subtype = xmlSchemaParseAny(ctxt, schema, child);
7338 } else if (IS_SCHEMA(child, "choice")) {
7339 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7340 } else if (IS_SCHEMA(child, "sequence")) {
7341 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7342 }
7343 if (subtype != NULL) {
7344 if (last == NULL) {
7345 type->subtypes = subtype;
7346 last = subtype;
7347 } else {
7348 last->next = subtype;
7349 last = subtype;
7350 }
7351 last->next = NULL;
7352 }
7353 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 }
7355 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007356 xmlSchemaPContentErr(ctxt,
7357 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
7358 NULL, type, node, child, NULL,
7359 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007360 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007361 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007362
7363 return (type);
7364}
7365
7366/**
7367 * xmlSchemaParseRestriction:
7368 * @ctxt: a schema validation context
7369 * @schema: the schema being built
7370 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00007371 *
7372 * parse a XML schema Restriction definition
7373 * *WARNING* this interface is highly subject to change
7374 *
7375 * Returns the type definition or NULL in case of error
7376 */
7377static xmlSchemaTypePtr
7378xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007379 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007380{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007381 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007382 xmlNodePtr child = NULL;
7383 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007384 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00007385 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007386
7387 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7388 return (NULL);
7389
7390 oldcontainer = ctxt->container;
7391
William M. Brack2f2a6632004-08-20 23:09:47 +00007392 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
7393 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007394 if (type == NULL)
7395 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007396 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007397 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007398 /*
7399 * Check for illegal attributes.
7400 */
7401 attr = node->properties;
7402 while (attr != NULL) {
7403 if (attr->ns == NULL) {
7404 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7405 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
7406 xmlSchemaPIllegalAttrErr(ctxt,
7407 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7408 NULL, type, attr);
7409 }
7410 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7411 xmlSchemaPIllegalAttrErr(ctxt,
7412 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7413 NULL, type, attr);
7414 }
7415 attr = attr->next;
7416 }
7417 /*
7418 * Extract and validate attributes.
7419 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007420 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007421 /*
7422 * Attribute "base".
7423 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007424 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00007425 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00007426 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7427 /* TODO: Think about the error code. */
7428 xmlSchemaPMissingAttrErr(ctxt,
7429 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
7430 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007431 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007432 /*
7433 * And now for the children...
7434 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007435 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007436 child = node->children;
7437 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007438 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7439 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007440 }
7441 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007442 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7443 if (IS_SCHEMA(child, "all")) {
7444 subtype = (xmlSchemaTypePtr)
7445 xmlSchemaParseAll(ctxt, schema, child);
7446 child = child->next;
7447 type->subtypes = subtype;
7448 } else if (IS_SCHEMA(child, "choice")) {
7449 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7450 child = child->next;
7451 type->subtypes = subtype;
7452 } else if (IS_SCHEMA(child, "sequence")) {
7453 subtype = (xmlSchemaTypePtr)
7454 xmlSchemaParseSequence(ctxt, schema, child);
7455 child = child->next;
7456 type->subtypes = subtype;
7457 } else if (IS_SCHEMA(child, "group")) {
7458 subtype = (xmlSchemaTypePtr)
7459 xmlSchemaParseGroup(ctxt, schema, child, 0);
7460 child = child->next;
7461 type->subtypes = subtype;
7462 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007463 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
7464 if (IS_SCHEMA(child, "simpleType")) {
7465 if (type->base != NULL) {
7466 /*
7467 * src-restriction-base-or-simpleType
7468 * Either the base [attribute] or the simpleType [child] of the
7469 * <restriction> element must be present, but not both.
7470 */
7471 xmlSchemaPContentErr(ctxt,
7472 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
7473 NULL, NULL, type->node, child,
7474 "The attribute 'base' and the <simpleType> child are "
7475 "mutually exclusive", NULL);
7476 } else {
7477 subtype = (xmlSchemaTypePtr)
7478 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7479 type->baseType = subtype;
7480 }
7481 child = child->next;
7482 }
7483 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007484 if (IS_SCHEMA(child, "simpleType")) {
7485 subtype = (xmlSchemaTypePtr)
7486 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007487 type->subtypes = subtype;
7488 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007489 }
7490 }
7491 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
7492 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
7493 xmlSchemaFacetPtr facet, lastfacet = NULL;
7494
Daniel Veillard01fa6152004-06-29 17:04:39 +00007495 /*
7496 * Add the facets to the parent simpleType/complexType.
7497 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007498 /*
7499 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
7500 * Simple Type Definition Schema Representation Constraint:
7501 * *Single Facet Value*
7502 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007503 while ((IS_SCHEMA(child, "minInclusive")) ||
7504 (IS_SCHEMA(child, "minExclusive")) ||
7505 (IS_SCHEMA(child, "maxInclusive")) ||
7506 (IS_SCHEMA(child, "maxExclusive")) ||
7507 (IS_SCHEMA(child, "totalDigits")) ||
7508 (IS_SCHEMA(child, "fractionDigits")) ||
7509 (IS_SCHEMA(child, "pattern")) ||
7510 (IS_SCHEMA(child, "enumeration")) ||
7511 (IS_SCHEMA(child, "whiteSpace")) ||
7512 (IS_SCHEMA(child, "length")) ||
7513 (IS_SCHEMA(child, "maxLength")) ||
7514 (IS_SCHEMA(child, "minLength"))) {
7515 facet = xmlSchemaParseFacet(ctxt, schema, child);
7516 if (facet != NULL) {
7517 if (lastfacet == NULL)
7518 ctxt->ctxtType->facets = facet;
7519 else
7520 lastfacet->next = facet;
7521 lastfacet = facet;
7522 lastfacet->next = NULL;
7523 }
7524 child = child->next;
7525 }
7526 /*
7527 * Create links for derivation and validation.
7528 */
7529 if (lastfacet != NULL) {
7530 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
7531
7532 facet = ctxt->ctxtType->facets;
7533 do {
7534 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
7535 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007536 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007537 xmlFree(facetLink);
7538 return (NULL);
7539 }
7540 facetLink->facet = facet;
7541 facetLink->next = NULL;
7542 if (lastFacetLink == NULL)
7543 ctxt->ctxtType->facetSet = facetLink;
7544 else
7545 lastFacetLink->next = facetLink;
7546 lastFacetLink = facetLink;
7547 facet = facet->next;
7548 } while (facet != NULL);
7549 }
7550 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007551 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
7552 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7553 if (IS_SCHEMA(child, "anyAttribute")) {
7554 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
7555 child = child->next;
7556 }
7557 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007559 /* TODO: Think about the error code. */
7560 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
7561 xmlSchemaPContentErr(ctxt,
7562 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7563 NULL, type, node, child, NULL,
7564 "annotation?, (group | all | choice | sequence)?, "
7565 "((attribute | attributeGroup)*, anyAttribute?))");
7566 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
7567 xmlSchemaPContentErr(ctxt,
7568 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7569 NULL, type, node, child, NULL,
7570 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7571 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7572 "length | minLength | maxLength | enumeration | whiteSpace | "
7573 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
7574 } else {
7575 /* Simple type */
7576 xmlSchemaPContentErr(ctxt,
7577 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
7578 NULL, type, node, child, NULL,
7579 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
7580 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
7581 "length | minLength | maxLength | enumeration | whiteSpace | "
7582 "pattern)*))");
7583 }
7584 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 ctxt->container = oldcontainer;
7586 return (type);
7587}
7588
7589/**
7590 * xmlSchemaParseExtension:
7591 * @ctxt: a schema validation context
7592 * @schema: the schema being built
7593 * @node: a subtree containing XML Schema informations
7594 *
7595 * parse a XML schema Extension definition
7596 * *WARNING* this interface is highly subject to change
7597 *
7598 * Returns the type definition or NULL in case of error
7599 */
7600static xmlSchemaTypePtr
7601xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007602 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007603{
7604 xmlSchemaTypePtr type, subtype;
7605 xmlNodePtr child = NULL;
7606 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007607 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007608
7609 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7610 return (NULL);
7611
7612 oldcontainer = ctxt->container;
7613
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007614 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007615 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007616 if (type == NULL)
7617 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007618 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007619 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007620 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007621 ctxt->container = name;
7622
7623 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
7624 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007625 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 "<extension>: The attribute \"base\" is missing.\n",
7627 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007628 }
7629 child = node->children;
7630 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007631 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7632 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007633 }
7634 subtype = NULL;
7635
7636 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007637 subtype = xmlSchemaParseAll(ctxt, schema, child);
7638 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007639 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007640 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007642 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007643 subtype = xmlSchemaParseSequence(ctxt, schema, child);
7644 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007645 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007646 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007647 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007648 }
7649 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007650 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007651 if ((ctxt->ctxtType != NULL) &&
7652 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
7653 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
7654 if (IS_SCHEMA(child, "anyAttribute")) {
7655 ctxt->ctxtType->attributeWildcard =
7656 xmlSchemaParseAnyAttribute(ctxt, schema, child);
7657 child = child->next;
7658 }
7659 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007660 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007661 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007662 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
7663 "<extension> has unexpected content.\n", type->name,
7664 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007665 }
7666 ctxt->container = oldcontainer;
7667 return (type);
7668}
7669
7670/**
7671 * xmlSchemaParseSimpleContent:
7672 * @ctxt: a schema validation context
7673 * @schema: the schema being built
7674 * @node: a subtree containing XML Schema informations
7675 *
7676 * parse a XML schema SimpleContent definition
7677 * *WARNING* this interface is highly subject to change
7678 *
7679 * Returns the type definition or NULL in case of error
7680 */
7681static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007682xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
7683 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007684{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007685 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007686 xmlNodePtr child = NULL;
7687 xmlChar name[30];
7688
7689 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7690 return (NULL);
7691
William M. Bracke7091952004-05-11 15:09:58 +00007692 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007693 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007694 if (type == NULL)
7695 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007696 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00007697 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007698 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007699
7700 child = node->children;
7701 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007702 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7703 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007704 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007705 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007706 ctxt->parentItem = type;
7707 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007708 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007709 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007710 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007711 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007712 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007713 subtype = (xmlSchemaTypePtr)
7714 xmlSchemaParseExtension(ctxt, schema, child);
7715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007716 }
7717 type->subtypes = subtype;
7718 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007719 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
7721 "<simpleContent> has unexpected content.\n",
7722 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007723 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007724 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007725 return (type);
7726}
7727
7728/**
7729 * xmlSchemaParseComplexContent:
7730 * @ctxt: a schema validation context
7731 * @schema: the schema being built
7732 * @node: a subtree containing XML Schema informations
7733 *
7734 * parse a XML schema ComplexContent definition
7735 * *WARNING* this interface is highly subject to change
7736 *
7737 * Returns the type definition or NULL in case of error
7738 */
7739static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007740xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
7741 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007742{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007743 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007744 xmlNodePtr child = NULL;
7745 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007746 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007747
7748 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7749 return (NULL);
7750
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007751 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007752 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 if (type == NULL)
7754 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007755 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007756 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007757 /*
7758 * Check for illegal attributes.
7759 */
7760 attr = node->properties;
7761 while (attr != NULL) {
7762 if (attr->ns == NULL) {
7763 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7764 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
7765 {
7766 xmlSchemaPIllegalAttrErr(ctxt,
7767 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7768 NULL, NULL, attr);
7769 }
7770 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7771 xmlSchemaPIllegalAttrErr(ctxt,
7772 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7773 NULL, NULL, attr);
7774 }
7775 attr = attr->next;
7776 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007777 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007778 /*
7779 * Handle attribute 'mixed'.
7780 */
7781 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
7782 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
7783 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
7784 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007785 child = node->children;
7786 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007787 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7788 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007789 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007790 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007791 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007792 subtype = NULL;
7793 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007794 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007795 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007796 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007797 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007798 subtype = (xmlSchemaTypePtr)
7799 xmlSchemaParseExtension(ctxt, schema, child);
7800 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007801 }
7802 type->subtypes = subtype;
7803 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007804 xmlSchemaPContentErr(ctxt,
7805 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7806 NULL, NULL, node, child,
7807 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007808 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007809 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007810 return (type);
7811}
7812
7813/**
7814 * xmlSchemaParseComplexType:
7815 * @ctxt: a schema validation context
7816 * @schema: the schema being built
7817 * @node: a subtree containing XML Schema informations
7818 *
7819 * parse a XML schema Complex Type definition
7820 * *WARNING* this interface is highly subject to change
7821 *
7822 * Returns the type definition or NULL in case of error
7823 */
7824static xmlSchemaTypePtr
7825xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007826 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007827{
Daniel Veillard01fa6152004-06-29 17:04:39 +00007828 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00007829 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007830 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007831 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007832 xmlAttrPtr attr;
7833 const xmlChar *attrValue;
7834 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00007835 char buf[40];
7836
Daniel Veillard4255d502002-04-16 15:50:10 +00007837
7838 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7839 return (NULL);
7840
Daniel Veillard01fa6152004-06-29 17:04:39 +00007841 ctxtType = ctxt->ctxtType;
7842
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007843 if (topLevel) {
7844 attr = xmlSchemaGetPropNode(node, "name");
7845 if (attr == NULL) {
7846 xmlSchemaPMissingAttrErr(ctxt,
7847 XML_SCHEMAP_S4S_ATTR_MISSING,
7848 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
7849 "name", NULL);
7850 return (NULL);
7851 } else if (xmlSchemaPValAttrNode(ctxt,
7852 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
7853 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7854 return (NULL);
7855 }
7856 }
7857
7858 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007859 /*
7860 * Parse as local complex type definition.
7861 */
7862 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
7863 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
7864 if (type == NULL)
7865 return (NULL);
7866 name = (const xmlChar *) buf;
7867 type->node = node;
7868 type->type = XML_SCHEMA_TYPE_COMPLEX;
7869 /*
7870 * TODO: We need the target namespace.
7871 */
7872 } else {
7873 /*
7874 * Parse as global complex type definition.
7875 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007876 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007877 if (type == NULL)
7878 return (NULL);
7879 type->node = node;
7880 type->type = XML_SCHEMA_TYPE_COMPLEX;
7881 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7882 /*
7883 * Set defaults.
7884 */
7885 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7886 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
7887 }
7888 /*
7889 * Handle attributes.
7890 */
7891 attr = node->properties;
7892 while (attr != NULL) {
7893 if (attr->ns == NULL) {
7894 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7895 /*
7896 * Attribute "id".
7897 */
7898 type->id = xmlSchemaGetProp(ctxt, node, "id");
7899 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
7900 /*
7901 * Attribute "mixed".
7902 */
7903 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7904 (xmlNodePtr) attr))
7905 type->flags |= XML_SCHEMAS_TYPE_MIXED;
7906 } else if (topLevel) {
7907 /*
7908 * Attributes of global complex type definitions.
7909 */
7910 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7911 /* Pass. */
7912 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
7913 /*
7914 * Attribute "abstract".
7915 */
7916 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
7917 (xmlNodePtr) attr))
7918 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
7919 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
7920 /*
7921 * Attribute "final".
7922 */
7923 attrValue = xmlSchemaGetNodeContent(ctxt,
7924 (xmlNodePtr) attr);
7925 if (xmlSchemaPValAttrBlockFinal(attrValue,
7926 &(type->flags),
7927 -1,
7928 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
7929 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
7930 -1, -1, -1) != 0)
7931 {
7932 xmlSchemaPSimpleTypeErr(ctxt,
7933 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7934 &des, type, (xmlNodePtr) attr,
7935 NULL,
7936 "(#all | List of (extension | restriction))",
7937 attrValue, NULL, NULL, NULL);
7938 }
7939 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
7940 /*
7941 * Attribute "block".
7942 */
7943 attrValue = xmlSchemaGetNodeContent(ctxt,
7944 (xmlNodePtr) attr);
7945 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7946 -1,
7947 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
7948 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
7949 -1, -1, -1) != 0) {
7950 xmlSchemaPSimpleTypeErr(ctxt,
7951 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7952 &des, type, (xmlNodePtr) attr,
7953 NULL,
7954 "(#all | List of (extension | restriction)) ",
7955 attrValue, NULL, NULL, NULL);
7956 }
7957 } else {
7958 xmlSchemaPIllegalAttrErr(ctxt,
7959 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7960 &des, type, attr);
7961 }
7962 } else {
7963 xmlSchemaPIllegalAttrErr(ctxt,
7964 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7965 &des, type, attr);
7966 }
7967 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7968 xmlSchemaPIllegalAttrErr(ctxt,
7969 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7970 &des, type, attr);
7971 }
7972 attr = attr->next;
7973 }
7974 /*
7975 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007976 * This will be only changed if a complex type
7977 * inherits an attribute wildcard from a base type.
7978 */
7979 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007980 /*
7981 * And now for the children...
7982 */
7983 oldcontainer = ctxt->container;
7984 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 child = node->children;
7986 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007987 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7988 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007989 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007990 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007991 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007992 /*
7993 * 3.4.3 : 2.2
7994 * Specifying mixed='true' when the <simpleContent>
7995 * alternative is chosen has no effect
7996 */
William M. Bracke7091952004-05-11 15:09:58 +00007997 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
7998 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007999 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8000 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008001 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008002 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8003 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008004 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008005 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008006 /*
8007 * Parse model groups.
8008 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008009 if (IS_SCHEMA(child, "all")) {
8010 subtype = xmlSchemaParseAll(ctxt, schema, child);
8011 child = child->next;
8012 } else if (IS_SCHEMA(child, "choice")) {
8013 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8014 child = child->next;
8015 } else if (IS_SCHEMA(child, "sequence")) {
8016 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8017 child = child->next;
8018 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008019 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008020 child = child->next;
8021 }
8022 if (subtype != NULL)
8023 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008024 /*
8025 * Parse attribute decls/refs.
8026 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008027 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008028 /*
8029 * Parse attribute wildcard.
8030 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008031 if (IS_SCHEMA(child, "anyAttribute")) {
8032 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8033 child = child->next;
8034 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008035 }
8036 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008037 xmlSchemaPContentErr(ctxt,
8038 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8039 &des, type, node, child,
8040 NULL, "(annotation?, (simpleContent | complexContent | "
8041 "((group | all | choice | sequence)?, ((attribute | "
8042 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008043 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008044 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008045 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008046 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008047 return (type);
8048}
8049
Daniel Veillard4255d502002-04-16 15:50:10 +00008050/**
8051 * xmlSchemaParseSchema:
8052 * @ctxt: a schema validation context
8053 * @node: a subtree containing XML Schema informations
8054 *
8055 * parse a XML schema definition from a node set
8056 * *WARNING* this interface is highly subject to change
8057 *
8058 * Returns the internal XML Schema structure built from the resource or
8059 * NULL in case of error
8060 */
8061static xmlSchemaPtr
8062xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8063{
8064 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008065 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008066 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008067 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008068
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008069 /*
8070 * This one is called by xmlSchemaParse only and is used if
8071 * the schema to be parsed was specified via the API; i.e. not
8072 * automatically by the validated instance document.
8073 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008074 if ((ctxt == NULL) || (node == NULL))
8075 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008076 nberrors = ctxt->nberrors;
8077 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008078 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008079 xmlSchemaImportPtr import;
8080
Daniel Veillard4255d502002-04-16 15:50:10 +00008081 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008082 if (schema == NULL)
8083 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008084 /*
8085 * Disable build of list of items.
8086 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008087 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8088 if (attr != NULL) {
8089 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8090 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8091 /*
8092 * TODO: Should we proceed with an invalid target namespace?
8093 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008094 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8095 } else {
8096 schema->targetNamespace = NULL;
8097 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008098 /*
8099 * Add the current ns name and location to the import table;
8100 * this is needed to have a consistent mechanism, regardless
8101 * if all schemata are constructed dynamically fired by the
8102 * instance or if the schema to be used was specified via
8103 * the API.
8104 */
8105 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8106 schema->targetNamespace);
8107 if (import == NULL) {
8108 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8109 NULL, NULL, (xmlNodePtr) ctxt->doc,
8110 "Internal error: xmlSchemaParseSchema, "
8111 "failed to add an import entry", NULL);
8112 xmlSchemaFree(schema);
8113 schema = NULL;
8114 return (NULL);
8115 }
8116 import->schemaLocation = ctxt->URL;
8117 /*
8118 * NOTE: We won't set the doc here, otherwise it will be freed
8119 * if the import struct is freed.
8120 * import->doc = ctxt->doc;
8121 */
8122
Daniel Veillardc0826a72004-08-10 14:17:33 +00008123 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008124 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008125 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8126 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8127
William M. Brack2f2a6632004-08-20 23:09:47 +00008128 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008129 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
8130 } else {
8131 xmlDocPtr doc;
8132
8133 doc = node->doc;
8134
8135 if ((doc != NULL) && (doc->URL != NULL)) {
8136 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8137 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008138 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008139 } else {
8140 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
8141 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008143 }
8144 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008145 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008146 if (ctxt->nberrors != 0) {
8147 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008148 xmlSchemaFree(schema);
8149 schema = NULL;
8150 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008151 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008152 if (schema != NULL)
8153 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008154 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00008155#ifdef DEBUG
8156 if (schema == NULL)
8157 xmlGenericError(xmlGenericErrorContext,
8158 "xmlSchemaParse() failed\n");
8159#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00008160 return (schema);
8161}
8162
8163/************************************************************************
8164 * *
8165 * Validating using Schemas *
8166 * *
8167 ************************************************************************/
8168
8169/************************************************************************
8170 * *
8171 * Reading/Writing Schemas *
8172 * *
8173 ************************************************************************/
8174
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008175#if 0 /* Will be enabled if it is clear what options are needed. */
8176/**
8177 * xmlSchemaParserCtxtSetOptions:
8178 * @ctxt: a schema parser context
8179 * @options: a combination of xmlSchemaParserOption
8180 *
8181 * Sets the options to be used during the parse.
8182 *
8183 * Returns 0 in case of success, -1 in case of an
8184 * API error.
8185 */
8186static int
8187xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
8188 int options)
8189
8190{
8191 int i;
8192
8193 if (ctxt == NULL)
8194 return (-1);
8195 /*
8196 * WARNING: Change the start value if adding to the
8197 * xmlSchemaParseOption.
8198 */
8199 for (i = 1; i < (int) sizeof(int) * 8; i++) {
8200 if (options & 1<<i) {
8201 return (-1);
8202 }
8203 }
8204 ctxt->options = options;
8205 return (0);
8206}
8207
8208/**
8209 * xmlSchemaValidCtxtGetOptions:
8210 * @ctxt: a schema parser context
8211 *
8212 * Returns the option combination of the parser context.
8213 */
8214static int
8215xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
8216
8217{
8218 if (ctxt == NULL)
8219 return (-1);
8220 else
8221 return (ctxt->options);
8222}
8223
8224 void *curItems; /* used for dynamic addition of schemata */
8225 int nbCurItems; /* used for dynamic addition of schemata */
8226 int sizeCurItems; /* used for dynamic addition of schemata */
8227
8228#endif
8229
Daniel Veillard4255d502002-04-16 15:50:10 +00008230/**
8231 * xmlSchemaNewParserCtxt:
8232 * @URL: the location of the schema
8233 *
8234 * Create an XML Schemas parse context for that file/resource expected
8235 * to contain an XML Schemas file.
8236 *
8237 * Returns the parser context or NULL in case of error
8238 */
8239xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008240xmlSchemaNewParserCtxt(const char *URL)
8241{
Daniel Veillard4255d502002-04-16 15:50:10 +00008242 xmlSchemaParserCtxtPtr ret;
8243
8244 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008245 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008246
8247 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8248 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008249 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008250 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008251 return (NULL);
8252 }
8253 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008254 ret->dict = xmlDictCreate();
8255 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008256 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008257 return (ret);
8258}
8259
8260/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008261 * xmlSchemaNewParserCtxtUseDict:
8262 * @URL: the location of the schema
8263 * @dict: the dictionary to be used
8264 *
8265 * Create an XML Schemas parse context for that file/resource expected
8266 * to contain an XML Schemas file.
8267 *
8268 * Returns the parser context or NULL in case of error
8269 */
8270static xmlSchemaParserCtxtPtr
8271xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8272{
8273 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008274 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008275 if (URL == NULL)
8276 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008277 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008278
8279 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8280 if (ret == NULL) {
8281 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8282 NULL);
8283 return (NULL);
8284 }
8285 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8286 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008287 xmlDictReference(dict);
8288 if (URL != NULL)
8289 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008290 ret->includes = 0;
8291 return (ret);
8292}
8293
8294
8295/**
Daniel Veillard6045c902002-10-09 21:13:59 +00008296 * xmlSchemaNewMemParserCtxt:
8297 * @buffer: a pointer to a char array containing the schemas
8298 * @size: the size of the array
8299 *
8300 * Create an XML Schemas parse context for that memory buffer expected
8301 * to contain an XML Schemas file.
8302 *
8303 * Returns the parser context or NULL in case of error
8304 */
8305xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008306xmlSchemaNewMemParserCtxt(const char *buffer, int size)
8307{
Daniel Veillard6045c902002-10-09 21:13:59 +00008308 xmlSchemaParserCtxtPtr ret;
8309
8310 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008311 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008312
8313 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8314 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008315 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008316 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00008317 return (NULL);
8318 }
8319 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8320 ret->buffer = buffer;
8321 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008322 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00008323 return (ret);
8324}
8325
8326/**
Daniel Veillard9d751502003-10-29 13:21:47 +00008327 * xmlSchemaNewDocParserCtxt:
8328 * @doc: a preparsed document tree
8329 *
8330 * Create an XML Schemas parse context for that document.
8331 * NB. The document may be modified during the parsing process.
8332 *
8333 * Returns the parser context or NULL in case of error
8334 */
8335xmlSchemaParserCtxtPtr
8336xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
8337{
8338 xmlSchemaParserCtxtPtr ret;
8339
8340 if (doc == NULL)
8341 return (NULL);
8342
8343 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8344 if (ret == NULL) {
8345 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8346 NULL);
8347 return (NULL);
8348 }
8349 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8350 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00008351 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00008352 /* The application has responsibility for the document */
8353 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00008354
8355 return (ret);
8356}
8357
8358/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008359 * xmlSchemaFreeParserCtxt:
8360 * @ctxt: the schema parser context
8361 *
8362 * Free the resources associated to the schema parser context
8363 */
8364void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008365xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
8366{
Daniel Veillard4255d502002-04-16 15:50:10 +00008367 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008368 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00008369 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008370 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008371 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008372 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008373 xmlFree(ctxt->assemble);
8374 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008375 if (ctxt->vctxt != NULL) {
8376 xmlSchemaFreeValidCtxt(ctxt->vctxt);
8377 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008378 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00008379 xmlFree(ctxt);
8380}
8381
8382/************************************************************************
8383 * *
8384 * Building the content models *
8385 * *
8386 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008387
Daniel Veillard4255d502002-04-16 15:50:10 +00008388/**
8389 * xmlSchemaBuildAContentModel:
8390 * @type: the schema type definition
8391 * @ctxt: the schema parser context
8392 * @name: the element name whose content is being built
8393 *
8394 * Generate the automata sequence needed for that type
8395 */
8396static void
8397xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008398 xmlSchemaParserCtxtPtr ctxt,
8399 const xmlChar * name)
8400{
Daniel Veillard4255d502002-04-16 15:50:10 +00008401 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008402 xmlGenericError(xmlGenericErrorContext,
8403 "Found unexpected type = NULL in %s content model\n",
8404 name);
8405 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008406 }
8407 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008408 case XML_SCHEMA_TYPE_ANY: {
8409 xmlAutomataStatePtr start, end;
8410 xmlSchemaWildcardPtr wild;
8411 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00008412
Daniel Veillardc0826a72004-08-10 14:17:33 +00008413 wild = type->attributeWildcard;
8414
8415 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008416 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008417 "Internal error: xmlSchemaBuildAContentModel, "
8418 "no wildcard on xsd:any.\n", NULL, NULL);
8419 return;
8420 }
8421
8422 start = ctxt->state;
8423 end = xmlAutomataNewState(ctxt->am);
8424
8425 if (type->maxOccurs == 1) {
8426 if (wild->any == 1) {
8427 /*
8428 * We need to add both transitions:
8429 *
8430 * 1. the {"*", "*"} for elements in a namespace.
8431 */
8432 ctxt->state =
8433 xmlAutomataNewTransition2(ctxt->am,
8434 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8435 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8436 /*
8437 * 2. the {"*"} for elements in no namespace.
8438 */
8439 ctxt->state =
8440 xmlAutomataNewTransition2(ctxt->am,
8441 start, NULL, BAD_CAST "*", NULL, type);
8442 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8443
8444 } else if (wild->nsSet != NULL) {
8445 ns = wild->nsSet;
8446 do {
8447 ctxt->state = start;
8448 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8449 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
8450 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8451 ns = ns->next;
8452 } while (ns != NULL);
8453
8454 } else if (wild->negNsSet != NULL) {
8455 xmlAutomataStatePtr deadEnd;
8456
8457 deadEnd = xmlAutomataNewState(ctxt->am);
8458 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8459 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8460 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8461 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8462 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8463 }
8464 } else {
8465 int counter;
8466 xmlAutomataStatePtr hop;
8467 int maxOccurs =
8468 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
8469 int minOccurs =
8470 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8471
8472 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8473 hop = xmlAutomataNewState(ctxt->am);
8474 if (wild->any == 1) {
8475 ctxt->state =
8476 xmlAutomataNewTransition2(ctxt->am,
8477 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8478 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8479 ctxt->state =
8480 xmlAutomataNewTransition2(ctxt->am,
8481 start, NULL, BAD_CAST "*", NULL, type);
8482 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8483 } else if (wild->nsSet != NULL) {
8484 ns = wild->nsSet;
8485 do {
8486 ctxt->state =
8487 xmlAutomataNewTransition2(ctxt->am,
8488 start, NULL, BAD_CAST "*", ns->value, type);
8489 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8490 ns = ns->next;
8491 } while (ns != NULL);
8492
8493 } else if (wild->negNsSet != NULL) {
8494 xmlAutomataStatePtr deadEnd;
8495
8496 deadEnd = xmlAutomataNewState(ctxt->am);
8497 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8498 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
8499 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8500 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
8501 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8502 }
8503 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
8504 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
8505 }
8506 if (type->minOccurs == 0) {
8507 xmlAutomataNewEpsilon(ctxt->am, start, end);
8508 }
8509 ctxt->state = end;
8510 break;
8511 }
8512 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008513 xmlAutomataStatePtr oldstate;
8514 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00008515
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008516 /*
8517 * IMPORTANT: This puts element declarations
8518 * (and never element decl. references) into the
8519 * automaton. This is crucial and should not be changed,
8520 * since validating functions rely now on it.
8521 */
8522 particle = (xmlSchemaElementPtr) type;
8523 if (particle->ref != NULL) {
8524 if (particle->refDecl == NULL) {
8525 /*
8526 * Skip content model creation if the reference
8527 * did not resolve to a declaration.
8528 */
8529 break;
8530 } else {
8531 /*
8532 * Referenced global element declaration.
8533 */
8534 elemDecl = particle->refDecl;
8535 }
8536 } else {
8537 /*
8538 * Anonymous element declaration.
8539 */
8540 elemDecl = particle;
8541 }
8542
8543 oldstate = ctxt->state;
8544
8545 if (particle->maxOccurs >= UNBOUNDED) {
8546 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008547 xmlAutomataStatePtr tmp;
8548 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008549
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008550 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008551 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008552 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008553 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008554 particle->minOccurs - 1, UNBOUNDED);
8555 ctxt->state =
8556 xmlAutomataNewTransition2(ctxt->am,
8557 ctxt->state, NULL,
8558 elemDecl->name,
8559 elemDecl->targetNamespace,
8560 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008561 tmp = ctxt->state;
8562 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008563 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008564 ctxt->state =
8565 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008566 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00008567
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008568 } else {
8569 ctxt->state =
8570 xmlAutomataNewTransition2(ctxt->am,
8571 ctxt->state, NULL,
8572 elemDecl->name,
8573 elemDecl->targetNamespace,
8574 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008575 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8576 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008577 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008578 /* basically an elem* */
8579 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8580 ctxt->state);
8581 }
8582 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008583 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008584 xmlAutomataStatePtr tmp;
8585 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00008586
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008587 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8588 oldstate, NULL);
8589 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008590 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008591 particle->minOccurs - 1,
8592 particle->maxOccurs - 1);
8593 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8594 ctxt->state,
8595 NULL,
8596 elemDecl->name,
8597 elemDecl->targetNamespace,
8598 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008599 tmp = ctxt->state;
8600 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008601 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008602 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008603 NULL, counter);
8604 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008605 /* basically an elem? */
8606 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008607 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008608 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00008609
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008610 } else {
8611 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
8612 ctxt->state,
8613 NULL,
8614 elemDecl->name,
8615 elemDecl->targetNamespace,
8616 (xmlSchemaTypePtr) elemDecl);
8617 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008618 /* basically an elem? */
8619 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008620 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008621 }
8622 }
8623 break;
8624 }
8625 case XML_SCHEMA_TYPE_SEQUENCE:{
8626 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008627
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 /*
8629 * If max and min occurances are default (1) then
8630 * simply iterate over the subtypes
8631 */
8632 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
8633 subtypes = type->subtypes;
8634 while (subtypes != NULL) {
8635 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8636 subtypes = subtypes->next;
8637 }
8638 } else {
8639 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008640
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008641 if (type->maxOccurs >= UNBOUNDED) {
8642 if (type->minOccurs > 1) {
8643 xmlAutomataStatePtr tmp;
8644 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008646 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8647 oldstate,
8648 NULL);
8649 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008650
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008651 counter = xmlAutomataNewCounter(ctxt->am,
8652 type->
8653 minOccurs - 1,
8654 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008655
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008656 subtypes = type->subtypes;
8657 while (subtypes != NULL) {
8658 xmlSchemaBuildAContentModel(subtypes, ctxt,
8659 name);
8660 subtypes = subtypes->next;
8661 }
8662 tmp = ctxt->state;
8663 xmlAutomataNewCountedTrans(ctxt->am, tmp,
8664 oldstate, counter);
8665 ctxt->state =
8666 xmlAutomataNewCounterTrans(ctxt->am, tmp,
8667 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00008668
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008669 } else {
8670 subtypes = type->subtypes;
8671 while (subtypes != NULL) {
8672 xmlSchemaBuildAContentModel(subtypes, ctxt,
8673 name);
8674 subtypes = subtypes->next;
8675 }
8676 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
8677 oldstate);
8678 if (type->minOccurs == 0) {
8679 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8680 ctxt->state);
8681 }
8682 }
8683 } else if ((type->maxOccurs > 1)
8684 || (type->minOccurs > 1)) {
8685 xmlAutomataStatePtr tmp;
8686 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00008687
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008688 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
8689 oldstate,
8690 NULL);
8691 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00008692
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008693 counter = xmlAutomataNewCounter(ctxt->am,
8694 type->minOccurs -
8695 1,
8696 type->maxOccurs -
8697 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00008698
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008699 subtypes = type->subtypes;
8700 while (subtypes != NULL) {
8701 xmlSchemaBuildAContentModel(subtypes, ctxt,
8702 name);
8703 subtypes = subtypes->next;
8704 }
8705 tmp = ctxt->state;
8706 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
8707 counter);
8708 ctxt->state =
8709 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
8710 counter);
8711 if (type->minOccurs == 0) {
8712 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8713 ctxt->state);
8714 }
Daniel Veillardb509f152002-04-17 16:28:10 +00008715
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008716 } else {
8717 subtypes = type->subtypes;
8718 while (subtypes != NULL) {
8719 xmlSchemaBuildAContentModel(subtypes, ctxt,
8720 name);
8721 subtypes = subtypes->next;
8722 }
8723 if (type->minOccurs == 0) {
8724 xmlAutomataNewEpsilon(ctxt->am, oldstate,
8725 ctxt->state);
8726 }
8727 }
8728 }
8729 break;
8730 }
8731 case XML_SCHEMA_TYPE_CHOICE:{
8732 xmlSchemaTypePtr subtypes;
8733 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00008734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008735 start = ctxt->state;
8736 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00008737
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008738 /*
8739 * iterate over the subtypes and remerge the end with an
8740 * epsilon transition
8741 */
8742 if (type->maxOccurs == 1) {
8743 subtypes = type->subtypes;
8744 while (subtypes != NULL) {
8745 ctxt->state = start;
8746 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8747 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8748 subtypes = subtypes->next;
8749 }
8750 } else {
8751 int counter;
8752 xmlAutomataStatePtr hop;
8753 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8754 UNBOUNDED : type->maxOccurs - 1;
8755 int minOccurs =
8756 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00008757
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008758 /*
8759 * use a counter to keep track of the number of transtions
8760 * which went through the choice.
8761 */
8762 counter =
8763 xmlAutomataNewCounter(ctxt->am, minOccurs,
8764 maxOccurs);
8765 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00008766
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008767 subtypes = type->subtypes;
8768 while (subtypes != NULL) {
8769 ctxt->state = start;
8770 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8771 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8772 subtypes = subtypes->next;
8773 }
8774 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8775 counter);
8776 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8777 counter);
8778 }
8779 if (type->minOccurs == 0) {
8780 xmlAutomataNewEpsilon(ctxt->am, start, end);
8781 }
8782 ctxt->state = end;
8783 break;
8784 }
8785 case XML_SCHEMA_TYPE_ALL:{
8786 xmlAutomataStatePtr start;
8787 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008788
Daniel Veillard3646d642004-06-02 19:19:14 +00008789 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008790 int lax;
8791
8792 subtypes = type->subtypes;
8793 if (subtypes == NULL)
8794 break;
8795 start = ctxt->state;
8796 while (subtypes != NULL) {
8797 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00008798 /*
8799 * the following 'if' was needed to fix bug 139897
8800 * not quite sure why it only needs to be done for
8801 * elements with a 'ref', but it seems to work ok.
8802 */
8803 if (subtypes->ref != NULL)
8804 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008805 elem = (xmlSchemaElementPtr) subtypes;
8806 /*
8807 * NOTE: The {max occurs} of all the particles in the
8808 * {particles} of the group must be 0 or 1.
8809 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008810 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008811 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
8812 ctxt->state,
8813 elem->name,
8814 elem->targetNamespace,
8815 1, 1, subtypes);
8816 } else if ((elem->minOccurs == 0) &&
8817 (elem->maxOccurs == 1)) {
8818
8819 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
8820 ctxt->state,
8821 elem->name,
8822 elem->targetNamespace,
8823 0,
8824 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008825 subtypes);
8826 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008827 /*
8828 * NOTE: if maxOccurs == 0 then no transition will be
8829 * created.
8830 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008831 subtypes = subtypes->next;
8832 }
8833 lax = type->minOccurs == 0;
8834 ctxt->state =
8835 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
8836 lax);
8837 break;
8838 }
8839 case XML_SCHEMA_TYPE_RESTRICTION:
8840 if (type->subtypes != NULL)
8841 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8842 break;
8843 case XML_SCHEMA_TYPE_EXTENSION:
8844 if (type->baseType != NULL) {
8845 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008846
8847 /*
8848 * TODO: Circular definitions will be checked at the
8849 * constraint level. So remove this when the complex type
8850 * constraints are implemented.
8851 */
Daniel Veillardf7627552004-04-22 07:15:40 +00008852 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008853 /* TODO: Change the error code. */
8854 xmlSchemaPCustomErr(ctxt,
8855 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
8856 NULL, type, type->node,
8857 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00008858 return;
8859 }
8860 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008861 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00008862 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 subtypes = type->subtypes;
8864 while (subtypes != NULL) {
8865 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
8866 subtypes = subtypes->next;
8867 }
8868 } else if (type->subtypes != NULL)
8869 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8870 break;
8871 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00008872 /*
8873 * Handle model group definition references.
8874 * NOTE: type->subtypes is the referenced model grop definition;
8875 * and type->subtypes->subtypes is the model group (i.e. <all> or
8876 * <choice> or <sequence>).
8877 */
8878 if ((type->ref != NULL) && (type->subtypes != NULL) &&
8879 (type->subtypes->subtypes != NULL)) {
8880 xmlSchemaTypePtr modelGr;
8881 xmlAutomataStatePtr start, end;
8882
8883 modelGr = type->subtypes->subtypes;
8884 start = ctxt->state;
8885 end = xmlAutomataNewState(ctxt->am);
8886 if (type->maxOccurs == 1) {
8887 ctxt->state = start;
8888 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8889 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
8890 } else {
8891 int counter;
8892 xmlAutomataStatePtr hop;
8893 int maxOccurs = type->maxOccurs == UNBOUNDED ?
8894 UNBOUNDED : type->maxOccurs - 1;
8895 int minOccurs =
8896 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
8897
8898 counter =
8899 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
8900 hop = xmlAutomataNewState(ctxt->am);
8901 ctxt->state = start;
8902 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
8903 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
8904 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
8905 counter);
8906 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
8907 counter);
8908 }
8909 if (type->minOccurs == 0) {
8910 xmlAutomataNewEpsilon(ctxt->am, start, end);
8911 }
8912 ctxt->state = end;
8913 break;
8914 }
8915 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008916 case XML_SCHEMA_TYPE_COMPLEX:
8917 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
8918 if (type->subtypes != NULL)
8919 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
8920 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00008921 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
8922 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008923 default:
8924 xmlGenericError(xmlGenericErrorContext,
8925 "Found unexpected type %d in %s content model\n",
8926 type->type, name);
8927 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008928 }
8929}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008930
Daniel Veillard4255d502002-04-16 15:50:10 +00008931/**
8932 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008933 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00008934 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008935 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00008936 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00008938 */
8939static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008940xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008941 xmlSchemaParserCtxtPtr ctxt,
8942 const xmlChar * name)
8943{
Daniel Veillard4255d502002-04-16 15:50:10 +00008944 xmlAutomataStatePtr start;
8945
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008946 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
8947 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
8948 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
8949 (type->contModel != NULL))
8950 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008951
8952#ifdef DEBUG_CONTENT
8953 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008954 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00008955#endif
8956
Daniel Veillard4255d502002-04-16 15:50:10 +00008957 ctxt->am = xmlNewAutomata();
8958 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008959 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008961 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00008962 }
8963 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008964 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008966 type->contModel = xmlAutomataCompile(ctxt->am);
8967 if (type->contModel == NULL) {
8968 xmlSchemaPCustomErr(ctxt,
8969 XML_SCHEMAP_INTERNAL,
8970 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008971 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008973 xmlSchemaPCustomErr(ctxt,
8974 XML_SCHEMAP_NOT_DETERMINISTIC,
8975 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008976 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008977 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00008978 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00008979#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008980 xmlGenericError(xmlGenericErrorContext,
8981 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00008983#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00008984 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00008985 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008986 xmlFreeAutomata(ctxt->am);
8987 ctxt->am = NULL;
8988}
8989
8990/**
8991 * xmlSchemaRefFixupCallback:
8992 * @elem: the schema element context
8993 * @ctxt: the schema parser context
8994 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00008995 * Resolves the references of an element declaration
8996 * or particle, which has an element declaration as it's
8997 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00008998 */
8999static void
9000xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009001 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009002 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009003 const xmlChar * context ATTRIBUTE_UNUSED,
9004 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009005{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009006 if ((ctxt == NULL) || (elem == NULL) ||
9007 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009008 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009009 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009010 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009011 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009012
Daniel Veillardc0826a72004-08-10 14:17:33 +00009013 /*
9014 * TODO: Evaluate, what errors could occur if the declaration is not
9015 * found. It might be possible that the "typefixup" might crash if
9016 * no ref declaration was found.
9017 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009018 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009019 if (elemDecl == NULL) {
9020 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009021 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009022 NULL, (xmlSchemaTypePtr) elem, elem->node,
9023 "ref", elem->ref, elem->refNs,
9024 XML_SCHEMA_TYPE_ELEMENT, NULL);
9025 } else
9026 elem->refDecl = elemDecl;
9027 } else {
9028 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9029 xmlSchemaTypePtr type;
9030
9031 /* (type definition) ... otherwise the type definition ·resolved·
9032 * to by the ·actual value· of the type [attribute] ...
9033 */
9034 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9035 elem->namedTypeNs);
9036 if (type == NULL) {
9037 xmlSchemaPResCompAttrErr(ctxt,
9038 XML_SCHEMAP_SRC_RESOLVE,
9039 NULL, (xmlSchemaTypePtr) elem, elem->node,
9040 "type", elem->namedType, elem->namedTypeNs,
9041 XML_SCHEMA_TYPE_BASIC, "type definition");
9042 } else
9043 elem->subtypes = type;
9044 }
9045 if (elem->substGroup != NULL) {
9046 xmlSchemaElementPtr substHead;
9047
9048 /*
9049 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9050 * substitutionGroup?
9051 */
9052 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009053 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009054 if (substHead == NULL) {
9055 xmlSchemaPResCompAttrErr(ctxt,
9056 XML_SCHEMAP_SRC_RESOLVE,
9057 NULL, (xmlSchemaTypePtr) elem, NULL,
9058 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9059 XML_SCHEMA_TYPE_ELEMENT, NULL);
9060 } else {
9061 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9062 /*
9063 * (type definition)...otherwise the {type definition} of the
9064 * element declaration ·resolved· to by the ·actual value· of
9065 * the substitutionGroup [attribute], if present
9066 */
9067 if (elem->subtypes == NULL)
9068 elem->subtypes = substHead->subtypes;
9069 }
9070 }
9071 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9072 (elem->substGroup == NULL))
9073 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9074 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009075}
9076
William M. Bracke7091952004-05-11 15:09:58 +00009077/**
9078 * xmlSchemaParseListRefFixup:
9079 * @type: the schema type definition
9080 * @ctxt: the schema parser context
9081 *
9082 * Fixup of the itemType reference of the list type.
9083 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009084static void
William M. Bracke7091952004-05-11 15:09:58 +00009085xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009086{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009087
Daniel Veillard01fa6152004-06-29 17:04:39 +00009088 if (((type->base == NULL) &&
9089 (type->subtypes == NULL)) ||
9090 ((type->base != NULL) &&
9091 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009092 /*
9093 * src-list-itemType-or-simpleType
9094 * Either the itemType [attribute] or the <simpleType> [child] of
9095 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009096 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009097 /*
9098 * TODO: Move this to the parse function.
9099 */
9100 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009101 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009102 NULL, type, type->node,
9103 "The attribute 'itemType' and the <simpleType> child "
9104 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009105 } else if (type->base!= NULL) {
9106 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9107 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009108 xmlSchemaPResCompAttrErr(ctxt,
9109 XML_SCHEMAP_SRC_RESOLVE,
9110 NULL, type, type->node,
9111 "itemType", type->base, type->baseNs,
9112 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009113 }
9114 }
9115 if ((type->subtypes != NULL) &&
9116 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9117 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009118}
9119
9120/**
9121 * xmlSchemaParseUnionRefCheck:
9122 * @typeDecl: the schema type definition
9123 * @ctxt: the schema parser context
9124 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00009125 * Checks and builds the memberTypes of the union type.
9126 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +00009127 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009128static int
William M. Bracke7091952004-05-11 15:09:58 +00009129xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +00009130 xmlSchemaParserCtxtPtr ctxt)
9131{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009132
Daniel Veillard01fa6152004-06-29 17:04:39 +00009133 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
9134 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +00009135
Daniel Veillard01fa6152004-06-29 17:04:39 +00009136 /* 1 If the <union> alternative is chosen, then [Definition:]
9137 * define the explicit members as the type definitions ·resolved·
9138 * to by the items in the ·actual value· of the memberTypes [attribute],
9139 * if any, followed by the type definitions corresponding to the
9140 * <simpleType>s among the [children] of <union>, if any.
9141 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009142
Daniel Veillard01fa6152004-06-29 17:04:39 +00009143 if (type->type != XML_SCHEMA_TYPE_UNION)
9144 return (-1);
9145 if (ctxt->ctxtType == NULL) {
9146 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009147 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009148 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
9149 "available", NULL, NULL);
9150 return (-1);
9151 }
9152 /*
9153 * src-union-memberTypes-or-simpleTypes
9154 * Either the memberTypes [attribute] of the <union> element must
9155 * be non-empty or there must be at least one simpleType [child].
9156 */
9157 if ((type->base == NULL) &&
9158 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009159 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009160 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009161 NULL, NULL, type->node,
9162 "Either the attribute 'memberTypes' must be non-empty "
9163 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009164 }
9165
9166 ctxtType = ctxt->ctxtType;
9167 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009168 xmlAttrPtr attr;
9169 const xmlChar *cur, *end;
9170 xmlChar *tmp;
9171 const xmlChar *localName, *uri;
9172
9173 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +00009174 cur = type->base;
9175 do {
9176 while (IS_BLANK_CH(*cur))
9177 cur++;
9178 end = cur;
9179 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9180 end++;
9181 if (end == cur)
9182 break;
9183 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009184 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
9185 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
9186 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009187 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009188 xmlSchemaPResCompAttrErr(ctxt,
9189 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
9190 NULL, NULL, type->node, "memberTypes", localName, uri,
9191 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009192 } else {
9193 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9194 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9195 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9196 if (link == NULL) {
9197 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9198 return (-1);
9199 }
9200 link->type = memberType;
9201 link->next = NULL;
9202 if (lastLink == NULL)
9203 ctxtType->memberTypes = link;
9204 else
9205 lastLink->next = link;
9206 lastLink = link;
9207 }
9208 xmlFree(tmp);
9209 cur = end;
9210 } while (*cur != 0);
9211 }
9212 /*
9213 * Add local simple types,
9214 */
9215 memberType = type->subtypes;
9216 while (memberType != NULL) {
9217 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
9218 xmlSchemaTypeFixup(memberType, ctxt, NULL);
9219 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
9220 if (link == NULL) {
9221 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
9222 return (-1);
9223 }
9224 link->type = memberType;
9225 link->next = NULL;
9226 if (lastLink == NULL)
9227 ctxtType->memberTypes = link;
9228 else
9229 lastLink->next = link;
9230 lastLink = link;
9231 memberType = memberType->next;
9232 }
9233 /*
9234 * The actual value is then formed by replacing any union type
9235 * definition in the ·explicit members· with the members of their
9236 * {member type definitions}, in order.
9237 */
9238 link = ctxtType->memberTypes;
9239 while (link != NULL) {
9240 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
9241 subLink = link->type->memberTypes;
9242 if (subLink != NULL) {
9243 link->type = subLink->type;
9244 if (subLink->next != NULL) {
9245 lastLink = link->next;
9246 subLink = subLink->next;
9247 prevLink = link;
9248 while (subLink != NULL) {
9249 newLink = (xmlSchemaTypeLinkPtr)
9250 xmlMalloc(sizeof(xmlSchemaTypeLink));
9251 if (newLink == NULL) {
9252 xmlSchemaPErrMemory(ctxt, "allocating a type link",
9253 NULL);
9254 return (-1);
9255 }
9256 newLink->type = memberType;
9257 prevLink->next = newLink;
9258 prevLink = newLink;
9259 newLink->next = lastLink;
9260
9261 subLink = subLink->next;
9262 }
9263 }
9264 }
9265 }
9266 link = link->next;
9267 }
9268
9269 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +00009270}
9271
Daniel Veillard4255d502002-04-16 15:50:10 +00009272/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009273 * xmlSchemaIsDerivedFromBuiltInType:
9274 * @ctxt: the schema parser context
9275 * @type: the type definition
9276 * @valType: the value type
9277 *
9278 *
9279 * Returns 1 if the type has the given value type, or
9280 * is derived from such a type.
9281 */
William M. Brack803812b2004-06-03 02:11:24 +00009282static int
Daniel Veillard3646d642004-06-02 19:19:14 +00009283xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
9284 xmlSchemaTypePtr type, int valType)
9285{
9286 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009287 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00009288 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009289 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +00009290 return(1);
9291 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
9292 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
9293 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
9294 ((xmlSchemaAttributePtr) type)->subtypes, valType));
9295 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
9296 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
9297 if (type->baseType != NULL)
9298 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
9299 valType));
9300 } else if ((type->subtypes != NULL) &&
9301 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
9302 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
9303 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
9304 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
9305 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
9306 valType));
9307 }
9308
9309 return (0);
9310}
9311
9312/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00009313 * xmlSchemaIsDerivedFromBuiltInType:
9314 * @type: the simpleType definition
9315 *
9316 * Returns the primitive type of the given type or
9317 * NULL in case of error.
9318 */
9319static xmlSchemaTypePtr
9320xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
9321{
9322 while (type != NULL) {
9323 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
9324 return (type);
9325 type = type->baseType;
9326 }
9327
9328 return (NULL);
9329}
9330
9331
9332/**
Daniel Veillard3646d642004-06-02 19:19:14 +00009333 * xmlSchemaBuildAttributeUsesOwned:
9334 * @ctxt: the schema parser context
9335 * @type: the complex type definition
9336 * @cur: the attribute declaration list
9337 * @lastUse: the top of the attribute use list
9338 *
9339 * Builds the attribute uses list on the given complex type.
9340 * This one is supposed to be called by
9341 * xmlSchemaBuildAttributeValidation only.
9342 */
9343static int
9344xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
9345 xmlSchemaAttributePtr cur,
9346 xmlSchemaAttributeLinkPtr *uses,
9347 xmlSchemaAttributeLinkPtr *lastUse)
9348{
9349 xmlSchemaAttributeLinkPtr tmp;
9350 while (cur != NULL) {
9351 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9352 /*
9353 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
9354 * to by the ·actual value·s of the ref [attribute] of the
9355 * <attributeGroup> [children], if any."
9356 */
9357 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
9358 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
9359 lastUse) == -1) {
9360 return (-1);
9361 }
9362 } else {
9363 /* W3C: "1 The set of attribute uses corresponding to the
9364 * <attribute> [children], if any."
9365 */
9366 tmp = (xmlSchemaAttributeLinkPtr)
9367 xmlMalloc(sizeof(xmlSchemaAttributeLink));
9368 if (tmp == NULL) {
9369 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
9370 return (-1);
9371 }
9372 tmp->attr = cur;
9373 tmp->next = NULL;
9374 if (*uses == NULL)
9375 *uses = tmp;
9376 else
9377 (*lastUse)->next = tmp;
9378 *lastUse = tmp;
9379 }
9380 cur = cur->next;
9381 }
9382 return (0);
9383}
9384
Daniel Veillard50355f02004-06-08 17:52:16 +00009385/**
9386 * xmlSchemaCloneWildcardNsConstraints:
9387 * @ctxt: the schema parser context
9388 * @dest: the destination wildcard
9389 * @source: the source wildcard
9390 *
9391 * Clones the namespace constraints of source
9392 * and assignes them to dest.
9393 * Returns -1 on internal error, 0 otherwise.
9394 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009395static int
9396xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
9397 xmlSchemaWildcardPtr *dest,
9398 xmlSchemaWildcardPtr source)
9399{
9400 xmlSchemaWildcardNsPtr cur, tmp, last;
9401
9402 if ((source == NULL) || (*dest == NULL))
9403 return(-1);
9404 (*dest)->any = source->any;
9405 cur = source->nsSet;
9406 last = NULL;
9407 while (cur != NULL) {
9408 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9409 if (tmp == NULL)
9410 return(-1);
9411 tmp->value = cur->value;
9412 if (last == NULL)
9413 (*dest)->nsSet = tmp;
9414 else
9415 last->next = tmp;
9416 last = tmp;
9417 cur = cur->next;
9418 }
9419 if ((*dest)->negNsSet != NULL)
9420 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
9421 if (source->negNsSet != NULL) {
9422 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9423 if ((*dest)->negNsSet == NULL)
9424 return(-1);
9425 (*dest)->negNsSet->value = source->negNsSet->value;
9426 } else
9427 (*dest)->negNsSet = NULL;
9428 return(0);
9429}
9430
Daniel Veillard50355f02004-06-08 17:52:16 +00009431/**
9432 * xmlSchemaUnionWildcards:
9433 * @ctxt: the schema parser context
9434 * @completeWild: the first wildcard
9435 * @curWild: the second wildcard
9436 *
9437 * Unions the namespace constraints of the given wildcards.
9438 * @completeWild will hold the resulting union.
9439 * Returns a positive error code on failure, -1 in case of an
9440 * internal error, 0 otherwise.
9441 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009442static int
9443xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
9444 xmlSchemaWildcardPtr completeWild,
9445 xmlSchemaWildcardPtr curWild)
9446{
9447 xmlSchemaWildcardNsPtr cur, curB, tmp;
9448
9449 /*
9450 * 1 If O1 and O2 are the same value, then that value must be the
9451 * value.
9452 */
9453 if ((completeWild->any == curWild->any) &&
9454 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9455 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9456
9457 if ((completeWild->negNsSet == NULL) ||
9458 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9459
9460 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009461 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009462
9463 /*
9464 * Check equality of sets.
9465 */
9466 cur = completeWild->nsSet;
9467 while (cur != NULL) {
9468 found = 0;
9469 curB = curWild->nsSet;
9470 while (curB != NULL) {
9471 if (cur->value == curB->value) {
9472 found = 1;
9473 break;
9474 }
9475 curB = curB->next;
9476 }
9477 if (!found)
9478 break;
9479 cur = cur->next;
9480 }
9481 if (found)
9482 return(0);
9483 } else
9484 return(0);
9485 }
9486 }
9487 /*
9488 * 2 If either O1 or O2 is any, then any must be the value
9489 */
Daniel Veillard50355f02004-06-08 17:52:16 +00009490 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009491 if (completeWild->any == 0) {
9492 completeWild->any = 1;
9493 if (completeWild->nsSet != NULL) {
9494 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9495 completeWild->nsSet = NULL;
9496 }
9497 if (completeWild->negNsSet != NULL) {
9498 xmlFree(completeWild->negNsSet);
9499 completeWild->negNsSet = NULL;
9500 }
9501 }
Daniel Veillard50355f02004-06-08 17:52:16 +00009502 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009503 }
9504 /*
9505 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
9506 * then the union of those sets must be the value.
9507 */
9508 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9509 int found;
9510 xmlSchemaWildcardNsPtr start;
9511
9512 cur = curWild->nsSet;
9513 start = completeWild->nsSet;
9514 while (cur != NULL) {
9515 found = 0;
9516 curB = start;
9517 while (curB != NULL) {
9518 if (cur->value == curB->value) {
9519 found = 1;
9520 break;
9521 }
9522 curB = curB->next;
9523 }
9524 if (!found) {
9525 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
9526 if (tmp == NULL)
9527 return (-1);
9528 tmp->value = cur->value;
9529 tmp->next = completeWild->nsSet;
9530 completeWild->nsSet = tmp;
9531 }
9532 cur = cur->next;
9533 }
9534
9535 return(0);
9536 }
9537 /*
9538 * 4 If the two are negations of different values (namespace names
9539 * or ·absent·), then a pair of not and ·absent· must be the value.
9540 */
9541 if ((completeWild->negNsSet != NULL) &&
9542 (curWild->negNsSet != NULL) &&
9543 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
9544 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +00009545
9546 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +00009547 }
9548 /*
9549 * 5.
9550 */
9551 if (((completeWild->negNsSet != NULL) &&
9552 (completeWild->negNsSet->value != NULL) &&
9553 (curWild->nsSet != NULL)) ||
9554 ((curWild->negNsSet != NULL) &&
9555 (curWild->negNsSet->value != NULL) &&
9556 (completeWild->nsSet != NULL))) {
9557
9558 int nsFound, absentFound = 0;
9559
9560 if (completeWild->nsSet != NULL) {
9561 cur = completeWild->nsSet;
9562 curB = curWild->negNsSet;
9563 } else {
9564 cur = curWild->nsSet;
9565 curB = completeWild->negNsSet;
9566 }
9567 nsFound = 0;
9568 while (cur != NULL) {
9569 if (cur->value == NULL)
9570 absentFound = 1;
9571 else if (cur->value == curB->value)
9572 nsFound = 1;
9573 if (nsFound && absentFound)
9574 break;
9575 cur = cur->next;
9576 }
9577
9578 if (nsFound && absentFound) {
9579 /*
9580 * 5.1 If the set S includes both the negated namespace
9581 * name and ·absent·, then any must be the value.
9582 */
9583 completeWild->any = 1;
9584 if (completeWild->nsSet != NULL) {
9585 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9586 completeWild->nsSet = NULL;
9587 }
9588 if (completeWild->negNsSet != NULL) {
9589 xmlFree(completeWild->negNsSet);
9590 completeWild->negNsSet = NULL;
9591 }
9592 } else if (nsFound && (!absentFound)) {
9593 /*
9594 * 5.2 If the set S includes the negated namespace name
9595 * but not ·absent·, then a pair of not and ·absent· must
9596 * be the value.
9597 */
9598 if (completeWild->nsSet != NULL) {
9599 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9600 completeWild->nsSet = NULL;
9601 }
9602 if (completeWild->negNsSet == NULL) {
9603 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9604 if (completeWild->negNsSet == NULL)
9605 return (-1);
9606 }
9607 completeWild->negNsSet->value = NULL;
9608 } else if ((!nsFound) && absentFound) {
9609 /*
9610 * 5.3 If the set S includes ·absent· but not the negated
9611 * namespace name, then the union is not expressible.
9612 */
9613 xmlSchemaPErr(ctxt, completeWild->node,
9614 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009615 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009616 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009617 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009618 } else if ((!nsFound) && (!absentFound)) {
9619 /*
9620 * 5.4 If the set S does not include either the negated namespace
9621 * name or ·absent·, then whichever of O1 or O2 is a pair of not
9622 * and a namespace name must be the value.
9623 */
9624 if (completeWild->negNsSet == NULL) {
9625 if (completeWild->nsSet != NULL) {
9626 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9627 completeWild->nsSet = NULL;
9628 }
9629 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9630 if (completeWild->negNsSet == NULL)
9631 return (-1);
9632 completeWild->negNsSet->value = curWild->negNsSet->value;
9633 }
9634 }
9635 return (0);
9636 }
9637 /*
9638 * 6.
9639 */
9640 if (((completeWild->negNsSet != NULL) &&
9641 (completeWild->negNsSet->value == NULL) &&
9642 (curWild->nsSet != NULL)) ||
9643 ((curWild->negNsSet != NULL) &&
9644 (curWild->negNsSet->value == NULL) &&
9645 (completeWild->nsSet != NULL))) {
9646
9647 if (completeWild->nsSet != NULL) {
9648 cur = completeWild->nsSet;
9649 } else {
9650 cur = curWild->nsSet;
9651 }
9652 while (cur != NULL) {
9653 if (cur->value == NULL) {
9654 /*
9655 * 6.1 If the set S includes ·absent·, then any must be the
9656 * value.
9657 */
9658 completeWild->any = 1;
9659 if (completeWild->nsSet != NULL) {
9660 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9661 completeWild->nsSet = NULL;
9662 }
9663 if (completeWild->negNsSet != NULL) {
9664 xmlFree(completeWild->negNsSet);
9665 completeWild->negNsSet = NULL;
9666 }
9667 return (0);
9668 }
9669 cur = cur->next;
9670 }
9671 if (completeWild->negNsSet == NULL) {
9672 /*
9673 * 6.2 If the set S does not include ·absent·, then a pair of not
9674 * and ·absent· must be the value.
9675 */
9676 if (completeWild->nsSet != NULL) {
9677 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
9678 completeWild->nsSet = NULL;
9679 }
9680 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
9681 if (completeWild->negNsSet == NULL)
9682 return (-1);
9683 completeWild->negNsSet->value = NULL;
9684 }
9685 return (0);
9686 }
9687 return (0);
9688
9689}
9690
Daniel Veillard50355f02004-06-08 17:52:16 +00009691/**
9692 * xmlSchemaIntersectWildcards:
9693 * @ctxt: the schema parser context
9694 * @completeWild: the first wildcard
9695 * @curWild: the second wildcard
9696 *
9697 * Intersects the namespace constraints of the given wildcards.
9698 * @completeWild will hold the resulting intersection.
9699 * Returns a positive error code on failure, -1 in case of an
9700 * internal error, 0 otherwise.
9701 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009702static int
9703xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
9704 xmlSchemaWildcardPtr completeWild,
9705 xmlSchemaWildcardPtr curWild)
9706{
William M. Brack803812b2004-06-03 02:11:24 +00009707 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +00009708
9709 /*
9710 * 1 If O1 and O2 are the same value, then that value must be the
9711 * value.
9712 */
9713 if ((completeWild->any == curWild->any) &&
9714 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
9715 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
9716
9717 if ((completeWild->negNsSet == NULL) ||
9718 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
9719
9720 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +00009721 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +00009722
9723 /*
9724 * Check equality of sets.
9725 */
9726 cur = completeWild->nsSet;
9727 while (cur != NULL) {
9728 found = 0;
9729 curB = curWild->nsSet;
9730 while (curB != NULL) {
9731 if (cur->value == curB->value) {
9732 found = 1;
9733 break;
9734 }
9735 curB = curB->next;
9736 }
9737 if (!found)
9738 break;
9739 cur = cur->next;
9740 }
9741 if (found)
9742 return(0);
9743 } else
9744 return(0);
9745 }
9746 }
9747 /*
9748 * 2 If either O1 or O2 is any, then the other must be the value.
9749 */
9750 if ((completeWild->any != curWild->any) && (completeWild->any)) {
9751 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9752 return(-1);
9753 return(0);
9754 }
9755 /*
9756 * 3 If either O1 or O2 is a pair of not and a value (a namespace
9757 * name or ·absent·) and the other is a set of (namespace names or
9758 * ·absent·), then that set, minus the negated value if it was in
9759 * the set, minus ·absent· if it was in the set, must be the value.
9760 */
9761 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
9762 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
9763 const xmlChar *neg;
9764
9765 if (completeWild->nsSet == NULL) {
9766 neg = completeWild->negNsSet->value;
9767 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
9768 return(-1);
9769 } else
9770 neg = curWild->negNsSet->value;
9771 /*
9772 * Remove absent and negated.
9773 */
9774 prev = NULL;
9775 cur = completeWild->nsSet;
9776 while (cur != NULL) {
9777 if (cur->value == NULL) {
9778 if (prev == NULL)
9779 completeWild->nsSet = cur->next;
9780 else
9781 prev->next = cur->next;
9782 xmlFree(cur);
9783 break;
9784 }
9785 prev = cur;
9786 cur = cur->next;
9787 }
9788 if (neg != NULL) {
9789 prev = NULL;
9790 cur = completeWild->nsSet;
9791 while (cur != NULL) {
9792 if (cur->value == neg) {
9793 if (prev == NULL)
9794 completeWild->nsSet = cur->next;
9795 else
9796 prev->next = cur->next;
9797 xmlFree(cur);
9798 break;
9799 }
9800 prev = cur;
9801 cur = cur->next;
9802 }
9803 }
9804
9805 return(0);
9806 }
9807 /*
9808 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
9809 * then the intersection of those sets must be the value.
9810 */
9811 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
9812 int found;
9813
9814 cur = completeWild->nsSet;
9815 prev = NULL;
9816 while (cur != NULL) {
9817 found = 0;
9818 curB = curWild->nsSet;
9819 while (curB != NULL) {
9820 if (cur->value == curB->value) {
9821 found = 1;
9822 break;
9823 }
9824 curB = curB->next;
9825 }
9826 if (!found) {
9827 if (prev == NULL)
9828 completeWild->nsSet = cur->next;
9829 else
9830 prev->next = cur->next;
9831 tmp = cur->next;
9832 xmlFree(cur);
9833 cur = tmp;
9834 continue;
9835 }
9836 prev = cur;
9837 cur = cur->next;
9838 }
9839
9840 return(0);
9841 }
9842 /* 5 If the two are negations of different namespace names,
9843 * then the intersection is not expressible
9844 */
9845 if ((completeWild->negNsSet != NULL) &&
9846 (curWild->negNsSet != NULL) &&
9847 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9848 (completeWild->negNsSet->value != NULL) &&
9849 (curWild->negNsSet->value != NULL)) {
9850
9851 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009852 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +00009853 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +00009854 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +00009855 }
9856 /*
9857 * 6 If the one is a negation of a namespace name and the other
9858 * is a negation of ·absent·, then the one which is the negation
9859 * of a namespace name must be the value.
9860 */
9861 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
9862 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
9863 (completeWild->negNsSet->value == NULL)) {
9864 completeWild->negNsSet->value = curWild->negNsSet->value;
9865 }
9866 return(0);
9867}
9868
Daniel Veillard50355f02004-06-08 17:52:16 +00009869/**
9870 * xmlSchemaIsWildcardNsConstraintSubset:
9871 * @ctxt: the schema parser context
9872 * @wildA: the first wildcard
9873 * @wildB: the second wildcard
9874 *
9875 * Returns 1 if the namespace constraint of @wildA is an intensional
9876 * subset of @wildB, 0 otherwise.
9877 */
9878static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00009879xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
9880 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +00009881{
Daniel Veillard3646d642004-06-02 19:19:14 +00009882
Daniel Veillard50355f02004-06-08 17:52:16 +00009883 /*
9884 * Schema Component Constraint: Wildcard Subset
9885 */
9886 /*
9887 * 1 super must be any.
9888 */
9889 if (wildB->any)
9890 return (1);
9891 /*
9892 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
9893 * 2.2 super must be a pair of not and the same value.
9894 */
9895 if ((wildA->negNsSet != NULL) &&
9896 (wildB->negNsSet != NULL) &&
9897 (wildA->negNsSet->value == wildA->negNsSet->value))
9898 return (1);
9899 /*
9900 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
9901 */
9902 if (wildA->nsSet != NULL) {
9903 /*
9904 * 3.2.1 super must be the same set or a superset thereof.
9905 */
9906 if (wildB->nsSet != NULL) {
9907 xmlSchemaWildcardNsPtr cur, curB;
9908 int found = 0;
9909
9910 cur = wildA->nsSet;
9911 while (cur != NULL) {
9912 found = 0;
9913 curB = wildB->nsSet;
9914 while (curB != NULL) {
9915 if (cur->value == curB->value) {
9916 found = 1;
9917 break;
9918 }
9919 curB = curB->next;
9920 }
9921 if (!found)
9922 return (0);
9923 cur = cur->next;
9924 }
9925 if (found)
9926 return (1);
9927 } else if (wildB->negNsSet != NULL) {
9928 xmlSchemaWildcardNsPtr cur;
9929 /*
9930 * 3.2.2 super must be a pair of not and a namespace name or
9931 * ·absent· and that value must not be in sub's set.
9932 */
9933 cur = wildA->nsSet;
9934 while (cur != NULL) {
9935 if (cur->value == wildB->negNsSet->value)
9936 return (0);
9937 cur = cur->next;
9938 }
9939 return (1);
9940 }
9941 }
9942 return (0);
9943}
9944
9945/**
9946 * xmlSchemaBuildCompleteAttributeWildcard:
9947 * @ctxt: the schema parser context
9948 * @attrs: the attribute list
9949 * @completeWild: the resulting complete wildcard
9950 *
9951 * Returns -1 in case of an internal error, 0 otherwise.
9952 */
9953static int
9954xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
9955 xmlSchemaAttributePtr attrs,
9956 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +00009957{
9958 while (attrs != NULL) {
9959 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
9960 xmlSchemaAttributeGroupPtr group;
9961
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009962 group = (xmlSchemaAttributeGroupPtr) attrs;
9963 /*
9964 * Handle attribute group references.
9965 */
9966 if (group->ref != NULL) {
9967 if (group->refItem == NULL) {
9968 /*
9969 * TODO: Should we raise a warning here?
9970 */
9971 /*
9972 * The referenced attribute group definition could not
9973 * be resolved beforehand, so skip.
9974 */
9975 attrs = attrs->next;
9976 continue;
9977 } else
9978 group = group->refItem;
9979 }
9980 /*
9981 * For every attribute group definition, an intersected wildcard
9982 * will be created (assumed that a wildcard exists on the
9983 * particular attr. gr. def. or on any contained attr. gr. def
9984 * at all).
9985 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
9986 * that the intersection will be performed only once.
9987 */
Daniel Veillard3646d642004-06-02 19:19:14 +00009988 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
9989 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009990 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
9991 group->attributes, &group->attributeWildcard) == -1)
9992 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +00009993 }
9994 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
9995 }
9996 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +00009997 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009998 /*
9999 * Copy the first encountered wildcard as context, except for the annotation.
10000 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010001 *completeWild = xmlSchemaAddWildcard(ctxt);
10002 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10003 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10004 completeWild, group->attributeWildcard) == -1)
10005 return (-1);
10006 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010007 /*
10008 * Although the complete wildcard might not correspond to any
10009 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010010 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010011 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010012 (*completeWild)->node = group->attributeWildcard->node;
10013
10014 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10015 xmlSchemaFreeWildcard(*completeWild);
10016 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010017 }
10018 }
10019 }
10020 attrs = attrs->next;
10021 }
10022
Daniel Veillard50355f02004-06-08 17:52:16 +000010023 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010024}
10025
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010026static int
10027xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10028 int *fixed,
10029 const xmlChar **value,
10030 xmlSchemaValPtr *val)
10031{
10032 *fixed = 0;
10033 *value = NULL;
10034 if (val != 0)
10035 *val = NULL;
10036
10037 if (item->defValue == NULL)
10038 item = item->refDecl;
10039
10040 if (item == NULL)
10041 return (0);
10042
10043 if (item->defValue != NULL) {
10044 *value = item->defValue;
10045 if (val != 0)
10046 *val = item->defVal;
10047 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10048 *fixed = 1;
10049 return (1);
10050 }
10051 return (0);
10052}
Daniel Veillard3646d642004-06-02 19:19:14 +000010053/**
10054 * xmlSchemaMatchesWildcardNs:
10055 * @wild: the wildcard
10056 * @ns: the namespace
10057 *
10058 *
10059 * Returns 1 if the given namespace matches the wildcard,
10060 * 0 otherwise.
10061 */
10062static int
10063xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10064{
10065 if (wild == NULL)
10066 return(0);
10067
10068 if (wild->any)
10069 return(1);
10070 else if (wild->nsSet != NULL) {
10071 xmlSchemaWildcardNsPtr cur;
10072
10073 cur = wild->nsSet;
10074 while (cur != NULL) {
10075 if (xmlStrEqual(cur->value, ns))
10076 return(1);
10077 cur = cur->next;
10078 }
10079 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10080 (!xmlStrEqual(wild->negNsSet->value, ns)))
10081 return(1);
10082
10083 return(0);
10084}
10085
10086/**
10087 * xmlSchemaBuildAttributeValidation:
10088 * @ctxt: the schema parser context
10089 * @type: the complex type definition
10090 *
10091 *
10092 * Builds the wildcard and the attribute uses on the given complex type.
10093 * Returns -1 if an internal error occurs, 0 otherwise.
10094 */
10095static int
10096xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10097{
10098 xmlSchemaTypePtr baseType = NULL;
10099 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010100 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010101 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010102 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010103 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010104 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010105 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010106
Daniel Veillard01fa6152004-06-29 17:04:39 +000010107 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010108 /*
10109 * Complex Type Definition with complex content Schema Component.
10110 *
10111 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010112 * TODO: Add checks for absent referenced attribute declarations and
10113 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010114 */
10115 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010116 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010117 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010118 "attribute uses already builded.\n",
10119 NULL, NULL);
10120 return (-1);
10121 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010122 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010123 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010124 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010125 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010126 type->name, NULL);
10127 return (-1);
10128 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010129 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010130 if (baseType == anyType)
10131 baseIsAnyType = 1;
10132 /*
10133 * Inherit the attribute uses of the base type.
10134 */
10135 /*
10136 * NOTE: It is allowed to "extend" the anyType complex type.
10137 */
10138 if (!baseIsAnyType) {
10139 if (baseType != NULL) {
10140 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
10141 tmp = (xmlSchemaAttributeLinkPtr)
10142 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10143 if (tmp == NULL) {
10144 xmlSchemaPErrMemory(ctxt,
10145 "building attribute uses of complexType", NULL);
10146 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010147 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010148 tmp->attr = cur->attr;
10149 tmp->next = NULL;
10150 if (type->attributeUses == NULL) {
10151 type->attributeUses = tmp;
10152 } else
10153 lastBaseUse->next = tmp;
10154 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010155 }
10156 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010157 }
10158 if ((type->subtypes != NULL) &&
10159 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10160 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010161 /*
10162 * type --> (<simpleContent>|<complexContent>)
10163 * --> (<restriction>|<extension>) --> attributes
10164 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010165 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010166 } else {
10167 /* Short hand form of the complexType. */
10168 attrs = type->attributes;
10169 }
10170 /*
10171 * Handle attribute wildcards.
10172 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010173 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10174 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010175 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010176 * NOTE: During the parse time, the wildcard is created on the complexType
10177 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010178 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010179 if (err == -1) {
10180 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
10181 "Internal error: xmlSchemaBuildAttributeValidation: "
10182 "failed to build an intersected attribute wildcard.\n",
10183 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010184 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010185 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010186
10187 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
10188 ((baseIsAnyType) ||
10189 ((baseType != NULL) &&
10190 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10191 (baseType->attributeWildcard != NULL)))) {
10192 if (type->attributeWildcard != NULL) {
10193 /*
10194 * Union the complete wildcard with the base wildcard.
10195 */
10196 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
10197 baseType->attributeWildcard) == -1)
10198 return (-1);
10199 } else {
10200 /*
10201 * Just inherit the wildcard.
10202 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010203 /*
10204 * NOTE: This is the only case where an attribute
10205 * wildcard is shared.
10206 */
10207 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
10208 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010209 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000010210 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010211 }
10212
10213 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10214 if (type->attributeWildcard != NULL) {
10215 /*
10216 * Derivation Valid (Restriction, Complex)
10217 * 4.1 The {base type definition} must also have one.
10218 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010219 if (baseType->attributeWildcard == NULL) {
10220 xmlSchemaPCustomErr(ctxt,
10221 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
10222 NULL, type, NULL,
10223 "The type has an attribute wildcard, "
10224 "but the base type %s does not have one",
10225 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10226 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010227 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010228 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010229 type->attributeWildcard, baseType->attributeWildcard) == 0) {
10230 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010231 xmlSchemaPCustomErr(ctxt,
10232 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
10233 NULL, type, NULL,
10234 "The attribute wildcard is not a valid "
10235 "subset of the wildcard in the base type %s",
10236 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10237 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010238 return (1);
10239 }
10240 /* 4.3 Unless the {base type definition} is the ·ur-type
10241 * definition·, the complex type definition's {attribute
10242 * wildcard}'s {process contents} must be identical to or
10243 * stronger than the {base type definition}'s {attribute
10244 * wildcard}'s {process contents}, where strict is stronger
10245 * than lax is stronger than skip.
10246 */
10247 if ((type->baseType != anyType) &&
10248 (type->attributeWildcard->processContents <
10249 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010250 xmlSchemaPCustomErr(ctxt,
10251 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
10252 NULL, type, NULL,
10253 "The 'process contents' of the attribute wildcard is weaker than "
10254 "the one in the base type %s",
10255 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10256 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010257 return (1);
10258 }
10259 }
10260 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10261 /*
10262 * Derivation Valid (Extension)
10263 * At this point the type and the base have both, either
10264 * no wildcard or a wildcard.
10265 */
10266 if ((baseType->attributeWildcard != NULL) &&
10267 (baseType->attributeWildcard != type->attributeWildcard)) {
10268 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010269 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010270 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010271 xmlSchemaPCustomErr(ctxt,
10272 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
10273 NULL, type, NULL,
10274 "The attribute wildcard is not a valid "
10275 "superset of the one in the base type %s",
10276 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10277 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010278 return (1);
10279 }
10280 }
10281 }
10282
Daniel Veillard3646d642004-06-02 19:19:14 +000010283 /*
10284 * Gather attribute uses defined by this type.
10285 */
10286 if (attrs != NULL) {
10287 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
10288 &uses, &lastUse) == -1) {
10289 return (-1);
10290 }
10291 }
10292 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
10293 * "Two distinct attribute declarations in the {attribute uses} must
10294 * not have identical {name}s and {target namespace}s."
10295 *
10296 * For "extension" this is done further down.
10297 */
10298 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
10299 cur = uses;
10300 while (cur != NULL) {
10301 tmp = cur->next;
10302 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010303 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10304 xmlSchemaGetAttrName(tmp->attr))) &&
10305 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10306 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
10307
10308 xmlSchemaPAttrUseErr(ctxt,
10309 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10310 NULL, type, NULL, cur->attr,
10311 "Duplicate attribute use %s specified",
10312 xmlSchemaFormatNsUriLocal(&str,
10313 xmlSchemaGetAttrTargetNsURI(tmp->attr),
10314 xmlSchemaGetAttrName(tmp->attr))
10315 );
10316 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010317 break;
10318 }
10319 tmp = tmp->next;
10320 }
10321 cur = cur->next;
10322 }
10323 }
10324 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
10325 /*
10326 * Derive by restriction.
10327 */
10328 if (baseIsAnyType) {
10329 type->attributeUses = uses;
10330 } else {
10331 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010332 const xmlChar *bEffValue;
10333 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000010334
10335 cur = uses;
10336 while (cur != NULL) {
10337 found = 0;
10338 base = type->attributeUses;
10339 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010340 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10341 xmlSchemaGetAttrName(base->attr)) &&
10342 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
10343 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010344
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010345 found = 1;
10346
Daniel Veillard3646d642004-06-02 19:19:14 +000010347 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
10348 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10349 /*
10350 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000010351 */
10352 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000010353 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010354 NULL, type, NULL, cur->attr,
10355 "The 'optional' use is inconsistent with a matching "
10356 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010357 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
10358 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
10359 /*
10360 * derivation-ok-restriction 3
10361 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010362 xmlSchemaPCustomErr(ctxt,
10363 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
10364 NULL, type, NULL,
10365 "A matching attribute use for the 'required' "
10366 "attribute use %s of the base type is missing",
10367 xmlSchemaFormatNsUriLocal(&str,
10368 xmlSchemaGetAttrTargetNsURI(base->attr),
10369 xmlSchemaGetAttrName(base->attr)));
10370 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000010371 } else {
10372 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010373 * 2.1.3 [Definition:] Let the effective value
10374 * constraint of an attribute use be its {value
10375 * constraint}, if present, otherwise its {attribute
10376 * declaration}'s {value constraint} .
10377 */
10378 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10379 &bEffValue, 0);
10380 /*
10381 * 2.1.3 ... one of the following must be true
10382 *
10383 * 2.1.3.1 B's ·effective value constraint· is
10384 * ·absent· or default.
10385 */
10386 if ((bEffValue != NULL) &&
10387 (effFixed == 1)) {
10388 const xmlChar *rEffValue = NULL;
10389
10390 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
10391 &rEffValue, 0);
10392 /*
10393 * 2.1.3.2 R's ·effective value constraint· is
10394 * fixed with the same string as B's.
10395 */
10396 if ((effFixed == 0) ||
10397 (! xmlStrEqual(rEffValue, bEffValue))) {
10398 xmlSchemaPAttrUseErr(ctxt,
10399 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
10400 NULL, type, NULL, cur->attr,
10401 "The effective value constraint of the "
10402 "attribute use is inconsistent with "
10403 "its correspondent of the base type",
10404 NULL);
10405 }
10406 }
10407 /*
10408 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
10409 */
10410 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000010411 * Override the attribute use.
10412 */
10413 base->attr = cur->attr;
10414 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010415
Daniel Veillard3646d642004-06-02 19:19:14 +000010416 break;
10417 }
10418 base = base->next;
10419 }
10420
10421 if (!found) {
10422 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10423 /*
10424 * derivation-ok-restriction 2.2
10425 */
10426 if ((type->attributeWildcard != NULL) &&
10427 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
10428 cur->attr->targetNamespace))
10429 found = 1;
10430
10431 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010432 xmlSchemaPAttrUseErr(ctxt,
10433 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
10434 NULL, type, NULL, cur->attr,
10435 "Neither a matching attribute use, "
10436 "nor a matching wildcard in the base type does exist",
10437 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000010438 } else {
10439 /*
10440 * Add the attribute use.
10441 *
10442 * Note that this may lead to funny derivation error reports, if
10443 * multiple equal attribute uses exist; but this is not
10444 * allowed anyway, and it will be reported beforehand.
10445 */
10446 tmp = cur;
10447 if (prev != NULL)
10448 prev->next = cur->next;
10449 else
10450 uses = cur->next;
10451 cur = cur->next;
10452 if (type->attributeUses == NULL) {
10453 type->attributeUses = tmp;
10454 } else
10455 lastBaseUse->next = tmp;
10456 lastBaseUse = tmp;
10457
10458 continue;
10459 }
10460 }
10461 }
10462 prev = cur;
10463 cur = cur->next;
10464 }
10465 if (uses != NULL)
10466 xmlSchemaFreeAttributeUseList(uses);
10467 }
10468 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10469 /*
10470 * The spec allows only appending, and not other kinds of extensions.
10471 *
10472 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
10473 */
10474 if (uses != NULL) {
10475 if (type->attributeUses == NULL) {
10476 type->attributeUses = uses;
10477 } else
10478 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010479 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010480 } else {
10481 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000010482 * Derive implicitely from the ur-type.
10483 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010484 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000010485 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010486 /*
10487 * 3.4.6 -> Complex Type Definition Properties Correct
10488 */
10489 if (type->attributeUses != NULL) {
10490 cur = type->attributeUses;
10491 prev = NULL;
10492 while (cur != NULL) {
10493 /*
10494 * 4. Two distinct attribute declarations in the {attribute uses} must
10495 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000010496 *
Daniel Veillard3646d642004-06-02 19:19:14 +000010497 * Note that this was already done for "restriction" and types derived from
10498 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000010499 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010500 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
10501 tmp = cur->next;
10502 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010503 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
10504 xmlSchemaGetAttrName(tmp->attr))) &&
10505 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
10506 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010507
Daniel Veillardc0826a72004-08-10 14:17:33 +000010508 xmlSchemaPAttrUseErr(ctxt,
10509 XML_SCHEMAP_CT_PROPS_CORRECT_4,
10510 NULL, type, NULL, tmp->attr,
10511 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010512 break;
10513 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010514 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010515 }
10516 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010517 /*
10518 * 5. Two distinct attribute declarations in the {attribute uses} must
10519 * not have {type definition}s which are or are derived from ID.
10520 */
10521 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000010522 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010523 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010524 xmlSchemaPAttrUseErr(ctxt,
10525 XML_SCHEMAP_CT_PROPS_CORRECT_5,
10526 NULL, type, NULL, cur->attr,
10527 "There must not exist more than one attribute use, "
10528 "declared of type 'ID' or derived from it",
10529 NULL);
10530 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000010531 }
Daniel Veillard3646d642004-06-02 19:19:14 +000010532 id = cur;
10533 }
10534 /*
10535 * Remove "prohibited" attribute uses. The reason this is done at this late
10536 * stage is to be able to catch dublicate attribute uses. So we had to keep
10537 * prohibited uses in the list as well.
10538 */
10539 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
10540 tmp = cur;
10541 if (prev == NULL)
10542 type->attributeUses = cur->next;
10543 else
10544 prev->next = cur->next;
10545 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000010546 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000010547 } else {
10548 prev = cur;
10549 cur = cur->next;
10550 }
10551 }
10552 }
10553 /*
10554 * TODO: This check should be removed if we are 100% sure of
10555 * the base type attribute uses already being built.
10556 */
10557 if ((baseType != NULL) && (!baseIsAnyType) &&
10558 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
10559 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010560 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010561 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010562 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010563 baseType->name, NULL);
10564 }
10565 return (0);
10566}
10567
10568/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010569 * xmlSchemaTypeFinalContains:
10570 * @schema: the schema
10571 * @type: the type definition
10572 * @final: the final
10573 *
10574 * Evaluates if a type definition contains the given "final".
10575 * This does take "finalDefault" into account as well.
10576 *
10577 * Returns 1 if the type does containt the given "final",
10578 * 0 otherwise.
10579 */
10580static int
10581xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
10582{
10583 int tfinal = final, tflags = type->flags;
10584
10585 if (type == NULL)
10586 return (0);
10587 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
10588 switch (final) {
10589 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
10590 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
10591 break;
10592 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
10593 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
10594 break;
10595 case XML_SCHEMAS_TYPE_FINAL_LIST:
10596 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
10597 break;
10598 case XML_SCHEMAS_TYPE_FINAL_UNION:
10599 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
10600 break;
10601 }
10602 tflags = schema->flags;
10603 }
10604 if (tflags & tfinal)
10605 return (1);
10606 else
10607 return (0);
10608
10609}
10610
10611/**
10612 * xmlSchemaGetUnionSimpleTypeMemberTypes:
10613 * @type: the Union Simple Type
10614 *
10615 * Returns a list of member types of @type if existing,
10616 * returns NULL otherwise.
10617 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000010618static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000010619xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
10620{
10621 while (type != NULL) {
10622 if (type->memberTypes != NULL)
10623 return (type->memberTypes);
10624 else
10625 type = type->baseType;
10626 }
10627 return (NULL);
10628}
10629
10630/**
10631 * xmlSchemaGetListSimpleTypeItemType:
10632 * @type: the simple type definition
10633 *
10634 * Returns the item type definition of the list simple type.
10635 */
10636static xmlSchemaTypePtr
10637xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
10638{
10639 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
10640 return (NULL);
10641 /*
10642 * Note: In libxml2, the built-in types do not reflect
10643 * the datatype hierarchy (yet?) - we have to treat them
10644 * in a special way.
10645 */
10646 if (type->type == XML_SCHEMA_TYPE_BASIC)
10647 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
10648 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
10649 /* 1 If the <list> alternative is chosen, then the type
10650 * definition ·resolved· to by the ·actual value· of the
10651 * itemType [attribute] of <list>, if present, otherwise
10652 * the type definition corresponding to the <simpleType>
10653 * among the [children] of <list>.
10654 */
10655 return (type->subtypes->subtypes);
10656 else {
10657 /* 2 If the <restriction> option is chosen, then the
10658 * {item type definition} of the {base type definition}.
10659 */
10660 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
10661 }
10662}
10663
10664/**
10665 * xmlSchemaCheckCOSSTDerivedOK:
10666 * @type: the derived simple type definition
10667 * @baseType: the base type definition
10668 *
10669 * Checks wheter @type can be validly
10670 * derived from @baseType.
10671 *
10672 * Returns 0 on success, an positive error code otherwise.
10673 */
10674static int
10675xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
10676 xmlSchemaTypePtr type,
10677 xmlSchemaTypePtr baseType,
10678 int subset)
10679{
10680 /*
10681 * Schema Component Constraint: Type Derivation OK (Simple)
10682 *
10683 *
10684 * 1 They are the same type definition.
10685 * TODO: The identy check might have to be more complex than this.
10686 */
10687 if (type == baseType)
10688 return (0);
10689 /*
10690 * 2.1 restriction is not in the subset, or in the {final}
10691 * of its own {base type definition};
10692 */
10693 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
10694 (xmlSchemaTypeFinalContains(schema,
10695 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
10696 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
10697 }
10698 /* 2.2 */
10699 if (type->baseType == baseType) {
10700 /*
10701 * 2.2.1 D's ·base type definition· is B.
10702 */
10703 return (0);
10704 }
10705 /*
10706 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
10707 * and is validly derived from B given the subset, as defined by this
10708 * constraint.
10709 */
10710 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
10711 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
10712 return (0);
10713 }
10714 /*
10715 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
10716 * definition·.
10717 */
10718 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10719 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
10720 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
10721 return (0);
10722 }
10723 /*
10724 * 2.2.4 B's {variety} is union and D is validly derived from a type
10725 * definition in B's {member type definitions} given the subset, as
10726 * defined by this constraint.
10727 *
10728 * NOTE: This seems not to involve built-in types, since there is no
10729 * built-in Union Simple Type.
10730 */
10731 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10732 xmlSchemaTypeLinkPtr cur;
10733
10734 cur = baseType->memberTypes;
10735 while (cur != NULL) {
10736 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
10737 cur->type, subset) == 0)
10738 return (0);
10739 cur = cur->next;
10740 }
10741 }
10742
10743 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
10744}
10745
10746
10747/**
10748 * xmlSchemaCheckSTPropsCorrect:
10749 * @ctxt: the schema parser context
10750 * @type: the simple type definition
10751 *
10752 * Checks st-props-correct.
10753 *
10754 * Returns 0 if the properties are correct,
10755 * if not, a positive error code and -1 on internal
10756 * errors.
10757 */
10758static int
10759xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
10760 xmlSchemaTypePtr type)
10761{
10762 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
10763 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010764 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010765
Daniel Veillardc0826a72004-08-10 14:17:33 +000010766 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010767 /*
10768 * Schema Component Constraint: Simple Type Definition Properties Correct
10769 *
10770 * NOTE: This is somehow redundant, since we actually built a simple type
10771 * to have all the needed information; this acts as an self test.
10772 */
10773 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
10774 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10775 /*
10776 * TODO: 1 The values of the properties of a simple type definition must be as
10777 * described in the property tableau in Datatype definition, modulo the
10778 * impact of Missing Sub-components (§5.3).
10779 */
10780 /* Base type: If the datatype has been ·derived· by ·restriction·
10781 * then the Simple Type Definition component from which it is ·derived·,
10782 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
10783 */
10784 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010785 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010786 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010787 NULL, type, NULL,
10788 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010789 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10790 }
10791 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
10792 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
10793 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010794 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010795 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010796 NULL, type, NULL,
10797 "The base type %s is not a simple type",
10798 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10799 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010800 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10801 }
10802 if ((baseType != anySimpleType) &&
10803 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010804 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010805 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010806 NULL, type, NULL,
10807 "A type, derived by list or union, must have"
10808 "the simple ur-type definition as base type, not %s",
10809 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10810 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010811 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10812 }
10813 /*
10814 * Variety: One of {atomic, list, union}.
10815 */
10816 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10817 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
10818 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010819 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010820 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010821 NULL, type, NULL,
10822 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010823 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
10824 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000010825 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010826
10827 /*
10828 * 2 All simple type definitions must be derived ultimately from the ·simple
10829 * ur-type definition (so· circular definitions are disallowed). That is, it
10830 * must be possible to reach a built-in primitive datatype or the ·simple
10831 * ur-type definition· by repeatedly following the {base type definition}.
10832 */
10833 baseType = type->baseType;
10834 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
10835 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10836 xmlSchemaTypeFixup(baseType, ctxt, NULL);
10837 if (baseType == anySimpleType)
10838 break;
10839 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010840 xmlSchemaPCustomErr(ctxt,
10841 XML_SCHEMAP_ST_PROPS_CORRECT_2,
10842 NULL, type, NULL,
10843 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010844 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
10845 }
10846 baseType = baseType->baseType;
10847 }
10848 /*
10849 * 3 The {final} of the {base type definition} must not contain restriction.
10850 */
10851 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
10852 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010853 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010854 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010855 NULL, type, NULL,
10856 "The 'final' of its base type %s must not contain "
10857 "'restriction'",
10858 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
10859 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010860 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
10861 }
10862 return (0);
10863}
10864
10865/**
10866 * xmlSchemaCheckDerivationValidSimpleRestriction:
10867 * @ctxt: the schema parser context
10868 * @type: the simple type definition
10869 *
10870 * Checks if the given @type (simpleType) is derived
10871 * validly by restriction.
10872 *
10873 * Returns -1 on internal errors, 0 if the type is validly derived,
10874 * a positive error code otherwise.
10875 */
10876static int
10877xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010878 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010879{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010880 xmlChar *str = NULL;
10881
10882 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010883
10884 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
10885 xmlSchemaPErr(ctxt, type->node,
10886 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010887 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
10888 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010889 type->name, NULL);
10890 return (-1);
10891 }
10892
10893 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
10894 xmlSchemaTypePtr primitive;
10895 /*
10896 * 1.1 The {base type definition} must be an atomic simple
10897 * type definition or a built-in primitive datatype.
10898 */
10899 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010900 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010901 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010902 NULL, type, NULL,
10903 "The base type %s is not an atomic simple type",
10904 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10905 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010906 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
10907 }
10908 /* 1.2 The {final} of the {base type definition} must not contain
10909 * restriction.
10910 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010911 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010912 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
10913 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010914 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010915 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010916 NULL, type, NULL,
10917 "The final of its base type %s must not contain 'restriction'",
10918 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
10919 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010920 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
10921 }
10922
10923 /*
10924 * 1.3.1 DF must be an allowed constraining facet for the {primitive
10925 * type definition}, as specified in the appropriate subsection of 3.2
10926 * Primitive datatypes.
10927 */
10928 if (type->facets != NULL) {
10929 xmlSchemaFacetPtr facet;
10930 int ok = 1;
10931
10932 primitive = xmlSchemaGetPrimitiveType(type);
10933 if (primitive == NULL) {
10934 xmlSchemaPErr(ctxt, type->node,
10935 XML_ERR_INTERNAL_ERROR,
10936 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010937 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010938 type->name, NULL);
10939 return (-1);
10940 }
10941 facet = type->facets;
10942 do {
10943 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010944 ok = 0;
10945 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010946 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010947 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010948 }
10949 facet = facet->next;
10950 } while (facet != NULL);
10951 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000010952 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010953 }
10954 /*
10955 * TODO: 1.3.2 (facet derivation)
10956 */
10957 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
10958 xmlSchemaTypePtr itemType = NULL;
10959
10960 itemType = xmlSchemaGetListSimpleTypeItemType(type);
10961 if (itemType == NULL) {
10962 xmlSchemaPErr(ctxt, type->node,
10963 XML_ERR_INTERNAL_ERROR,
10964 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000010965 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000010966 type->name, NULL);
10967 return (-1);
10968 }
10969 /*
10970 * 2.1 The {item type definition} must have a {variety} of atomic or
10971 * union (in which case all the {member type definitions}
10972 * must be atomic).
10973 */
10974 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
10975 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010976 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010977 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010978 NULL, type, NULL,
10979 "The item type %s must have a variety of atomic or union",
10980 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
10981 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010982 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10983 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10984 xmlSchemaTypeLinkPtr member;
10985
10986 member = itemType->memberTypes;
10987 while (member != NULL) {
10988 if ((member->type->flags &
10989 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010990 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010991 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010992 NULL, type, NULL,
10993 "The item type is a union type, but the "
10994 "member type %s of this item type is not atomic",
10995 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
10996 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010997 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
10998 }
10999 member = member->next;
11000 }
11001 }
11002
11003 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11004 xmlSchemaFacetPtr facet;
11005 /*
11006 * This is the case if we have: <simpleType><list ..
11007 */
11008 /*
11009 * 2.3.1
11010 * 2.3.1.1 The {final} of the {item type definition} must not
11011 * contain list.
11012 */
11013 if (xmlSchemaTypeFinalContains(ctxt->schema,
11014 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011015 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011016 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011017 NULL, type, NULL,
11018 "The final of its item type %s must not contain 'list'",
11019 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11020 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011021 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11022 }
11023 /*
11024 * 2.3.1.2 The {facets} must only contain the whiteSpace
11025 * facet component.
11026 */
11027 if (type->facets != NULL) {
11028 facet = type->facets;
11029 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011030 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11031 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011032 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011033 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011034 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11035 }
11036 facet = facet->next;
11037 } while (facet != NULL);
11038 }
11039 /*
11040 * TODO: Datatypes states:
11041 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11042 * whose ·lexical space· allows space (such as string or anyURI)or
11043 * a ·union· datatype any of whose {member type definitions}'s
11044 * ·lexical space· allows space.
11045 */
11046 } else {
11047 /*
11048 * This is the case if we have: <simpleType><restriction ...
11049 */
11050 /*
11051 * 2.3.2
11052 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11053 */
11054 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011055 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011056 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011057 NULL, type, NULL,
11058 "The base type %s must be a list type",
11059 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11060 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011061 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11062 }
11063 /*
11064 * 2.3.2.2 The {final} of the {base type definition} must not
11065 * contain restriction.
11066 */
11067 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11068 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011069 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011070 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 NULL, type, NULL,
11072 "The final of the base type %s must not contain 'restriction'",
11073 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11074 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011075 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11076 }
11077 /*
11078 * 2.3.2.3 The {item type definition} must be validly derived
11079 * from the {base type definition}'s {item type definition} given
11080 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11081 */
11082 {
11083 xmlSchemaTypePtr baseItemType;
11084
11085 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11086 if (baseItemType == NULL) {
11087 xmlSchemaPErr(ctxt, type->node,
11088 XML_ERR_INTERNAL_ERROR,
11089 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011090 "List simple type '%s': Failed to "
11091 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011092 type->name, type->baseType->name);
11093 return (-1);
11094 }
11095 if ((itemType != baseItemType) &&
11096 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11097 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 xmlChar *strBIT = NULL, *strBT = NULL;
11099 xmlSchemaPCustomErrExt(ctxt,
11100 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11101 NULL, type, NULL,
11102 "The item type %s is not validly derived from the "
11103 "item type %s of the base type %s",
11104 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11105 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11106 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11107
11108 FREE_AND_NULL(str)
11109 FREE_AND_NULL(strBIT)
11110 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011111 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11112 }
11113 }
11114
11115 if (type->facets != NULL) {
11116 xmlSchemaFacetPtr facet;
11117 int ok = 1;
11118 /*
11119 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11120 * and enumeration facet components are allowed among the {facets}.
11121 */
11122 facet = type->facets;
11123 do {
11124 switch (facet->type) {
11125 case XML_SCHEMA_FACET_LENGTH:
11126 case XML_SCHEMA_FACET_MINLENGTH:
11127 case XML_SCHEMA_FACET_MAXLENGTH:
11128 case XML_SCHEMA_FACET_WHITESPACE:
11129 /*
11130 * TODO: 2.5.1.2 List datatypes
11131 * The value of ·whiteSpace· is fixed to the value collapse.
11132 */
11133 case XML_SCHEMA_FACET_PATTERN:
11134 case XML_SCHEMA_FACET_ENUMERATION:
11135 break;
11136 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011137 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011138 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011140 /*
11141 * We could return, but it's nicer to report all
11142 * invalid facets.
11143 */
11144 ok = 0;
11145 }
11146 }
11147 facet = facet->next;
11148 } while (facet != NULL);
11149 if (ok == 0)
11150 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
11151 /*
11152 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
11153 * is a facet of the same kind in the {facets} of the {base type
11154 * definition} (call this BF),then the DF's {value} must be a valid
11155 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
11156 */
11157 }
11158
11159
11160 }
11161 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11162 /*
11163 * 3.1 The {member type definitions} must all have {variety} of
11164 * atomic or list.
11165 */
11166 xmlSchemaTypeLinkPtr member;
11167
11168 member = type->memberTypes;
11169 while (member != NULL) {
11170 if (((member->type->flags &
11171 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11172 ((member->type->flags &
11173 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011174 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011175 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011176 NULL, type, NULL,
11177 "The member type %s is neither an atomic, nor a list type",
11178 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11179 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011180 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
11181 }
11182 member = member->next;
11183 }
11184 /*
11185 * 3.3.1 If the {base type definition} is the ·simple ur-type
11186 * definition·
11187 */
11188 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11189 /*
11190 * 3.3.1.1 All of the {member type definitions} must have a
11191 * {final} which does not contain union.
11192 */
11193 member = type->memberTypes;
11194 while (member != NULL) {
11195 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
11196 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011197 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011198 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011199 NULL, type, NULL,
11200 "The final of member type %s contains 'union'",
11201 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11202 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011203 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
11204 }
11205 member = member->next;
11206 }
11207 /*
11208 * 3.3.1.2 The {facets} must be empty.
11209 */
11210 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011211 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011212 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011213 NULL, type, NULL,
11214 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011215 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
11216 }
11217 } else {
11218 /*
11219 * 3.3.2.1 The {base type definition} must have a {variety} of union.
11220 */
11221 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011222 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011223 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011224 NULL, type, NULL,
11225 "The base type %s is not a union type",
11226 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11227 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011228 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
11229 }
11230 /*
11231 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
11232 */
11233 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11234 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011235 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011236 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011237 NULL, type, NULL,
11238 "The final of its base type %s must not contain 'restriction'",
11239 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11240 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011241 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
11242 }
11243 /*
11244 * 3.3.2.3 The {member type definitions}, in order, must be validly
11245 * derived from the corresponding type definitions in the {base
11246 * type definition}'s {member type definitions} given the empty set,
11247 * as defined in Type Derivation OK (Simple) (§3.14.6).
11248 */
11249 {
11250 xmlSchemaTypeLinkPtr baseMember;
11251
11252 /*
11253 * OPTIMIZE: if the type is restricting, it has no local defined
11254 * member types and inherits the member types of the base type;
11255 * thus a check for equality can be skipped.
11256 */
11257 /*
11258 * TODO: Even worse: I cannot see a scenario where a restricting
11259 * union simple type can have other member types as the member
11260 * types of it's base type. This check seems not necessary with
11261 * respect to the derivation process in libxml2.
11262 */
11263 if (type->memberTypes != NULL) {
11264 member = type->memberTypes;
11265 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
11266 if ((member == NULL) && (baseMember != NULL)) {
11267 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011268 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011269 "Internal error: "
11270 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011271 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011272 "of member types in the base type\n",
11273 type->name, NULL);
11274 }
11275 while (member != NULL) {
11276 if (baseMember == NULL) {
11277 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011278 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011279 "Internal error: "
11280 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011281 "(3.3.2.3), union simple type '%s', unequal number "
11282 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011283 type->name, NULL);
11284 }
11285 if ((member->type != baseMember->type) &&
11286 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
11287 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011288 xmlChar *strBMT = NULL, *strBT = NULL;
11289
11290 xmlSchemaPCustomErrExt(ctxt,
11291 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
11292 NULL, type, NULL,
11293 "The member type %s is not validly derived from its "
11294 "corresponding member type %s of the base type %s",
11295 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
11296 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
11297 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11298 FREE_AND_NULL(str)
11299 FREE_AND_NULL(strBMT)
11300 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011301 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
11302 }
11303 member = member->next;
11304 baseMember = baseMember->next;
11305 }
11306 }
11307 }
11308 /*
11309 * 3.3.2.4 Only pattern and enumeration facet components are
11310 * allowed among the {facets}.
11311 */
11312 if (type->facets != NULL) {
11313 xmlSchemaFacetPtr facet;
11314 int ok = 1;
11315
11316 facet = type->facets;
11317 do {
11318 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
11319 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011320 xmlSchemaPIllegalFacetListUnionErr(ctxt,
11321 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
11322 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011323 ok = 0;
11324 }
11325 facet = facet->next;
11326 } while (facet != NULL);
11327 if (ok == 0)
11328 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
11329
11330 }
11331 /*
11332 * TODO: 3.3.2.5 (facet derivation)
11333 */
11334 }
11335 }
11336
11337 return (0);
11338}
11339
11340/**
11341 * xmlSchemaCheckSRCSimpleType:
11342 * @ctxt: the schema parser context
11343 * @type: the simple type definition
11344 *
11345 * Checks crc-simple-type constraints.
11346 *
11347 * Returns 0 if the constraints are satisfied,
11348 * if not a positive error code and -1 on internal
11349 * errors.
11350 */
11351static int
11352xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
11353 xmlSchemaTypePtr type)
11354{
11355 /*
11356 * NOTE: src-simple-type 2-4 are redundant, since the checks
11357 * were are done for the corresponding <restriction>, <list> and <union>
11358 * elements, but W3C wants a <simpleType> error as well, so it gets one.
11359 * Maby this can be skipped in the future, if we get sure it's not needed.
11360 */
11361 if (type->subtypes == NULL) {
11362 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011363 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011364 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011365 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011366 type->name, NULL);
11367 return (-1);
11368 }
11369 /*
11370 * src-simple-type.1 The corresponding simple type definition, if any,
11371 * must satisfy the conditions set out in Constraints on Simple Type
11372 * Definition Schema Components (§3.14.6).
11373 */
11374 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
11375 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
11376 /*
11377 * TODO: Removed this, since it got annoying to get an
11378 * extra error report, if anything failed until now.
11379 * Enable this if needed.
11380 */
11381 /*
11382 xmlSchemaPErr(ctxt, type->node,
11383 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011384 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000011385 "on simple type definitions.\n",
11386 type->name, NULL);
11387 */
11388 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
11389 }
11390
11391 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
11392 /*
11393 * src-simple-type.2 If the <restriction> alternative is chosen,
11394 * either it must have a base [attribute] or a <simpleType> among its
11395 * [children], but not both.
11396 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011397 /*
11398 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
11399 * NOTE: This was removed, since this will be already handled
11400 * in the parse function for <restriction>.
11401 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011402 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
11403 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
11404 * an itemType [attribute] or a <simpleType> among its [children],
11405 * but not both.
11406 * NOTE: baseType is set to the local simple type definiton,
11407 * if existent, at parse time. This is a hack and not nice.
11408 */
William M. Brack2f2a6632004-08-20 23:09:47 +000011409 /*
11410 * TODO: Remove this, and add the check to the parse function of <list>.
11411 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011412 if (((type->subtypes->base == NULL) &&
11413 (type->baseType == NULL)) ||
11414 ((type->subtypes->base != NULL) &&
11415 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011416 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011417 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 NULL, type, NULL,
11419 "Either the attribute 'itemType' or the <simpleType> child "
11420 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011421 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
11422 }
11423
11424
11425 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
11426 xmlSchemaTypeLinkPtr member;
11427 xmlSchemaTypePtr ancestor, anySimpleType;
11428
11429 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11430
11431 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
11432 * the <union> alternative is chosen, there must not be any entries
11433 * in the memberTypes [attribute] at any depth which resolve to the
11434 * component corresponding to the <simpleType>.
11435 */
11436 member = type->memberTypes;
11437 while (member != NULL) {
11438 ancestor = member->type;
11439 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
11440 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11441 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
11442 if (ancestor == anySimpleType)
11443 break;
11444 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011445 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011446 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011447 NULL, type, NULL,
11448 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011449 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
11450 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11451 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000011452 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000011453 * type as item type, which in turn has a list ST as member
11454 * type, we will assume this here as well, since this check
11455 * was not yet performed.
11456 */
11457
11458 }
11459 ancestor = ancestor->baseType;
11460 }
11461 member = member->next;
11462 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011463 }
11464
11465 return (0);
11466}
11467
William M. Brack2f2a6632004-08-20 23:09:47 +000011468#if 0 /* Not yet used code for CT schema validation */
11469static int
11470xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
11471 const xmlChar * value,
11472 xmlSchemaTypePtr type,
11473 int fireErrors)
11474{
11475 int ret;
11476 /*
11477 * 3.14.4 Simple Type Definition Validation Rules
11478 * Validation Rule: String Valid
11479 */
11480 /*
11481 * 1 It is schema-valid with respect to that definition as defined
11482 * by Datatype Valid in [XML Schemas: Datatypes].
11483 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011484 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
11485 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000011486 return (ret);
11487 /*
11488 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
11489 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
11490 * the string must be a ·declared entity name·.
11491 */
11492 /*
11493 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
11494 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
11495 * then every whitespace-delimited substring of the string must be a ·declared
11496 * entity name·.
11497 */
11498 /*
11499 * 2.3 otherwise no further condition applies.
11500 */
11501
11502 return (0);
11503}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011504#endif
11505
William M. Brack2f2a6632004-08-20 23:09:47 +000011506
11507static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011508xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
11509{
11510 if (vctxt->pctxt == NULL) {
11511 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
11512 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
11513 if (vctxt->pctxt == NULL) {
11514 xmlSchemaVErr(vctxt, NULL,
11515 XML_SCHEMAV_INTERNAL,
11516 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11517 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000011518 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011519 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011520 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011521 /* TODO: Pass user data. */
11522 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
11523 }
11524 return (0);
11525}
11526
11527static int
11528xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
11529{
11530 if (ctxt->vctxt == NULL) {
11531 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
11532 if (ctxt->vctxt == NULL) {
11533 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011534 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011535 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
11536 "failed to create a temp. validation context.\n",
11537 NULL, NULL);
11538 return (-1);
11539 }
11540 /* TODO: Pass user data. */
11541 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
11542 }
11543 return (0);
11544}
11545
11546/**
11547 * xmlSchemaCheckCOSValidDefault:
11548 * @ctxt: the schema parser context
11549 * @type: the simple type definition
11550 * @value: the default value
11551 * @node: an optional node (the holder of the value)
11552 *
11553 * Checks the "cos-valid-default" constraints.
11554 *
11555 * Returns 0 if the constraints are satisfied,
11556 * if not, a positive error code and -1 on internal
11557 * errors.
11558 */
11559static int
11560xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
11561 xmlSchemaValidCtxtPtr vctxt,
11562 xmlSchemaTypePtr type,
11563 const xmlChar *value,
11564 xmlNodePtr node)
11565{
11566 int ret = 0;
11567
11568 /*
11569 * cos-valid-default:
11570 * Schema Component Constraint: Element Default Valid (Immediate)
11571 * For a string to be a valid default with respect to a type
11572 * definition the appropriate case among the following must be true:
11573 */
11574 /*
11575 * NOTE: This has to work without a given node (the holder of the
11576 * value), since it should work on the component, i.e. an underlying
11577 * DOM must not be mandatory.
11578 */
11579 if ((pctxt == NULL) || (vctxt == NULL)) {
11580 xmlSchemaPErr(pctxt, node,
11581 XML_SCHEMAP_INTERNAL,
11582 "Internal error: xmlSchemaCheckCOSValidDefault, "
11583 "bad arguments: the parser and/or validation context is "
11584 "missing.\n",
11585 NULL, NULL);
11586 return (-1);
11587 }
11588 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011589 /*
11590 * Complex type.
11591 *
11592 * 2.1 its {content type} must be a simple type definition or mixed.
11593 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011594 /*
11595 * TODO: Adjust this when the content type will be computed
11596 * correctly.
11597 */
11598 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
11599 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
11600 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
11601 xmlSchemaPSimpleTypeErr(pctxt,
11602 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
11603 NULL, NULL, node,
11604 type, NULL, NULL,
11605 "If the type of a constraint value is complex, its content "
11606 "type must be mixed or a simple type",
11607 NULL, NULL);
11608 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
11609 }
11610 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000011611 /*
11612 * 2.2.2 If the {content type} is mixed, then the {content type}'s
11613 * particle must be ·emptiable· as defined by Particle Emptiable
11614 * (§3.9.6).
11615 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011616
William M. Brack2f2a6632004-08-20 23:09:47 +000011617 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011618 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000011619 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011620 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000011621 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011622 }
11623 /*
11624 * 1 If the type definition is a simple type definition, then the string
11625 * must be ·valid· with respect to that definition as defined by String
11626 * Valid (§3.14.4).
11627 *
11628 * AND
11629 *
11630 * 2.2.1 If the {content type} is a simple type definition, then the
11631 * string must be ·valid· with respect to that simple type definition
11632 * as defined by String Valid (§3.14.4).
11633 */
11634 vctxt->node = node;
11635 vctxt->cur = NULL;
11636 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
11637 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
11638 if (ret < 0) {
11639 xmlSchemaPErr(pctxt, node,
11640 /* NOTNICE: error code: This function will be used during
11641 * schema construction and xsi:type validation.
11642 */
11643 XML_SCHEMAP_INTERNAL,
11644 "Internal error: xmlSchemaCheckCOSValidDefault, "
11645 "while validating a value constaint value.\n",
11646 NULL, NULL);
11647
11648 }
11649 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000011650}
11651
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011652#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000011653/**
11654 * xmlSchemaGetSTContentOfCT:
11655 * @ctxt: the schema parser context
11656 * @type: the complex type definition
11657 *
11658 *
11659 * Returns the corresponding simple type for the content of
11660 * the complex type.
11661 */
11662static xmlSchemaTypePtr
11663xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
11664 xmlSchemaTypePtr type)
11665{
11666 xmlSchemaTypePtr orig = type, anyType;
11667
11668 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11669 while ((type != NULL) && (type != anyType) &&
11670 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11671 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
11672 return(type);
11673 type = type->baseType;
11674 }
11675 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011676 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011677 NULL, orig, NULL,
11678 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
11679 "no simple type for the content of complex type '%s' could be "
11680 "computed", orig->name);
11681 return (NULL);
11682}
11683
11684
William M. Brack2f2a6632004-08-20 23:09:47 +000011685
William M. Brack2f2a6632004-08-20 23:09:47 +000011686
11687/**
11688 * xmlSchemaCheckCOSCTExtends:
11689 * @ctxt: the schema parser context
11690 * @type: the complex type definition
11691 *
11692 * Schema Component Constraint: Derivation Valid (Extension)
11693 *
11694 * Returns 0 if the constraints are satisfied, a positive
11695 * error code if not and -1 if an internal error occured.
11696 */
11697static int
11698xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
11699 xmlSchemaTypePtr type)
11700{
11701 xmlSchemaTypePtr base;
11702 /*
11703 * 1 If the {base type definition} is a complex type definition,
11704 * then all of the following must be true:
11705 */
11706 base = type->baseType;
11707 if (base == NULL) {
11708 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011709 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000011710 NULL, type, NULL,
11711 "Internal error: xmlSchemaCheckCOSCTExtends, "
11712 "the complex type '%s' has no base type", type->name);
11713 return (-1);
11714 }
11715 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
11716 /*
11717 * 1.1 The {final} of the {base type definition} must not
11718 * contain extension.
11719 */
11720 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
11721 xmlSchemaPCustomErr(ctxt,
11722 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
11723 NULL, type, NULL,
11724 "The 'final' of the base type definition "
11725 "contains extension", NULL);
11726 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
11727 }
11728 /*
11729 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
11730 * of the complex type definition itself, that is, for every attribute
11731 * use in the {attribute uses} of the {base type definition}, there
11732 * must be an attribute use in the {attribute uses} of the complex
11733 * type definition itself whose {attribute declaration} has the same
11734 * {name}, {target namespace} and {type definition} as its attribute
11735 * declaration
11736 *
11737 * NOTE: This will be already satisfied by the way the attribute uses
11738 * are extended in xmlSchemaBuildAttributeValidation; thus this check
11739 * is not needed.
11740 */
11741
11742 /*
11743 * 1.3 If it has an {attribute wildcard}, the complex type definition
11744 * must also have one, and the base type definition's {attribute
11745 * wildcard}'s {namespace constraint} must be a subset of the complex
11746 * type definition's {attribute wildcard}'s {namespace constraint},
11747 * as defined by Wildcard Subset (§3.10.6).
11748 *
11749 * This is already checked in xmlSchemaBuildAttributeValidation; thus
11750 * this check is not needed.
11751 */
11752
11753 /*
11754 * 1.4 One of the following must be true:
11755 *
11756 * 1.4.1 The {content type} of the {base type definition} and the
11757 * {content type} of the complex type definition itself must be the same
11758 * simple type definition
11759 */
11760
11761
11762
11763 } else {
11764 /*
11765 * 2 If the {base type definition} is a simple type definition,
11766 * then all of the following must be true:
11767 */
11768 /*
11769 * 2.1 The {content type} must be the same simple type definition.
11770 */
11771 /*
11772 * 2.2 The {final} of the {base type definition} must not contain
11773 * extension
11774 */
11775 }
11776
11777}
11778
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011779static int
11780xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
11781 xmlSchemaTypePtr type)
11782{
11783 xmlSchemaTypePtr base, content;
11784 int OK = 0;
11785
11786 /*
11787 * TODO: Adjust the error codes here, as I used
11788 * XML_SCHEMAP_SRC_CT_1 only yet.
11789 */
11790 /*
11791 * Schema Representation Constraint:
11792 * Complex Type Definition Representation OK
11793 */
11794 base = type->baseType;
11795 if (base == NULL) {
11796 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
11797 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
11798 type->name);
11799 return (-1);
11800 }
11801
11802 if (type->subtypes != NULL) {
11803 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11804 if IS_COMPLEX_TYPE(base) {
11805 /*
11806 * 1 If the <complexContent> alternative is chosen, the type definition
11807 * ·resolved· to by the ·actual value· of the base [attribute]
11808 * must be a complex type definition;
11809 */
11810 xmlSchemaPCustomErr(ctxt,
11811 XML_SCHEMAP_SRC_CT_1,
11812 NULL, type, NULL,
11813 "The base type is not a complex type", NULL);
11814 return (XML_SCHEMAP_SRC_CT_1);
11815 }
11816 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11817
11818 if IS_SIMPLE_TYPE(base) {
11819 if (type->flags &
11820 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11821 /*
11822 * 2.1.3 only if the <extension> alternative is also
11823 * chosen, a simple type definition.
11824 */
11825 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
11826 xmlSchemaPCustomErr(ctxt,
11827 XML_SCHEMAP_SRC_CT_1,
11828 NULL, type, NULL,
11829 "A complex type (simple content) cannot restrict "
11830 "an other simple type",
11831 NULL);
11832 return (XML_SCHEMAP_SRC_CT_1);
11833 }
11834 OK = 1;
11835
11836 } else { /* if IS_SIMPLE_TYPE(base) */
11837 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
11838 /*
11839 * 2.1.2 only if the <restriction> alternative is also
11840 * chosen, a complex type definition whose {content type}
11841 * is mixed and a particle emptyable.
11842 */
11843 /*
11844 * FIXME TODO: Check for *empiable particle* is missing.
11845 */
11846 if ((type->flags &
11847 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
11848 xmlSchemaPCustomErr(ctxt,
11849 XML_SCHEMAP_SRC_CT_1,
11850 NULL, type, NULL,
11851 "A complex type (simple content) cannot "
11852 "extend an other complex type which has a "
11853 "content type of: 'mixed' and emptiable particle",
11854 NULL);
11855 return (XML_SCHEMAP_SRC_CT_1);
11856 }
11857 /*
11858 * NOTE: This will be fired as well, if the base type
11859 * is *'anyType'*.
11860 * NOTE: type->subtypes->subtypes will be the
11861 * <restriction> item.
11862 */
11863 if (type->subtypes->subtypes == NULL) {
11864 /* Yes, this is paranoid programming. */
11865 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11866 NULL, type, NULL,
11867 "Internal error: xmlSchemaCheckSRCCT, "
11868 "'%s', <simpleContent> has no <restriction>",
11869 type->name);
11870 return (-1);
11871 }
11872 /*
11873 * 2.2 If clause 2.1.2 above is satisfied, then there
11874 * must be a <simpleType> among the [children] of
11875 * <restriction>.
11876 */
11877 if (type->subtypes->subtypes->type !=
11878 XML_SCHEMA_TYPE_SIMPLE) {
11879 /* TODO: Change error code to ..._SRC_CT_2_2. */
11880 xmlSchemaPCustomErr(ctxt,
11881 XML_SCHEMAP_SRC_CT_1,
11882 NULL, type, NULL,
11883 "A <simpleType> is expected among the children "
11884 "of <restriction>", NULL);
11885 return (XML_SCHEMAP_SRC_CT_1);
11886 }
11887 OK = 1;
11888 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
11889 /*
11890 * 2.1.1 a complex type definition whose {content type} is a
11891 * simple type definition;
11892 */
11893 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
11894 xmlSchemaPCustomErr(ctxt,
11895 XML_SCHEMAP_SRC_CT_1,
11896 NULL, type, NULL,
11897 "A complex type (simple content) cannot "
11898 "be derived from the complex type '%s'",
11899 base->name);
11900 return (XML_SCHEMAP_SRC_CT_1);
11901 }
11902 content = base->contentTypeDef;
11903 if (content == NULL) {
11904 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
11905 NULL, type, NULL,
11906 "Internal error: xmlSchemaCheckSRCCT, "
11907 "'%s', base type has no content type",
11908 type->name);
11909 return (-1);
11910 }
11911 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
11912 xmlSchemaPCustomErr(ctxt,
11913 XML_SCHEMAP_SRC_CT_1,
11914 NULL, type, NULL,
11915 "A complex type (simple content) cannot "
11916 "be derived from the complex type '%s'",
11917 base->name);
11918 return (XML_SCHEMAP_SRC_CT_1);
11919 }
11920 }
11921 }
11922 }
11923 }
11924 /*
11925 * TODO: 3 The corresponding complex type definition component must
11926 * satisfy the conditions set out in Constraints on Complex Type
11927 * Definition Schema Components (§3.4.6);
11928 *
11929 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
11930 * above for {attribute wildcard} is satisfied, the intensional
11931 * intersection must be expressible, as defined in Attribute Wildcard
11932 * Intersection (§3.10.6).
11933 */
11934
11935}
William M. Brack2f2a6632004-08-20 23:09:47 +000011936#endif
11937
Daniel Veillard01fa6152004-06-29 17:04:39 +000011938/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011939 * xmlSchemaGroupDefFixup:
11940 * @typeDecl: the schema model group definition
11941 * @ctxt: the schema parser context
11942 *
11943 * Fixes model group definitions.
11944 */
11945static void
11946xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
11947 xmlSchemaParserCtxtPtr ctxt,
11948 const xmlChar * name ATTRIBUTE_UNUSED)
11949{
11950 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
11951 if ((group->ref != NULL) && (group->subtypes == NULL)) {
11952 xmlSchemaTypePtr groupDef;
11953 /*
11954 * Resolve the reference.
11955 */
11956 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
11957 group->refNs);
11958 if (groupDef == NULL) {
11959 xmlSchemaPResCompAttrErr(ctxt,
11960 XML_SCHEMAP_SRC_RESOLVE,
11961 NULL, group, NULL,
11962 "ref", group->ref, group->refNs,
11963 XML_SCHEMA_TYPE_GROUP, NULL);
11964 return;
11965 }
11966 group->subtypes = groupDef;
11967 }
11968}
11969
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011970#if 0 /* Enable when the content type will be computed. */
11971static int
11972xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
11973 xmlSchemaTypePtr type)
11974{
11975 xmlSchemaTypePtr base, res = NULL;
11976
11977 base = type->baseType;
11978 if (base == NULL) {
11979 xmlSchemaPCustomErr(ctxt,
11980 XML_SCHEMAP_INTERNAL,
11981 NULL, type, NULL,
11982 "Internal error: xmlSchemaGetContentType, "
11983 "the complex type '%s' has no base type", type->name);
11984 return (-1);
11985 }
11986 if (IS_ANYTYPE(base) || (type->subtypes->type ==
11987 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
11988 xmlSchemaTypePtr start;
11989 /*
11990 * Effective 'mixed'.
11991 */
11992 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11993 type->contentType = XML_SCHEMA_CONTENT_MIXED;
11994 /*
11995 * Effective content.
11996 */
11997 if (IS_ANYTYPE(base))
11998 start = type;
11999 else
12000 start = type->subtypes;
12001
12002 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12003 xmlSchemaTypePtr baseContentItem;
12004
12005 /*
12006 * Complex type with simple content.
12007 */
12008 if IS_COMPLEX_TYPE(base) {
12009 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12010 /*
12011 * Summary: a complex type (simple content) can *restrict*
12012 * a complex type with the following content type:
12013 * 1. 'mixed' and an emptiable particle
12014 * 2. simple type
12015 */
12016 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12017 /*
12018 * 2 if the {content type} of the base type is mixed and a
12019 * particle which is ·emptiable·,
12020 * [...]
12021 * then starting from the simple type definition
12022 * corresponding to the <simpleType> among the [children]
12023 * of <restriction> (**which must be present**)
12024 *
12025 * FIXME TODO: Handle "emptiable particle".
12026 */
12027 res = type->subtypes->subtypes;
12028 if (res == NULL) {
12029 xmlSchemaPCustomErr(ctxt,
12030 XML_SCHEMAP_INTERNAL,
12031 NULL, type, NULL,
12032 "Internal error: xmlSchemaGetContentType, "
12033 "CT '%s' (restricting): <simpleContent> has no "
12034 "<restriction>",
12035 type->name);
12036 return (-1);
12037 }
12038
12039 res->subtypes;
12040 if (res == NULL) {
12041 xmlSchemaPCustomErr(ctxt,
12042 XML_SCHEMAP_INTERNAL,
12043 NULL, type, NULL,
12044 "Internal error: xmlSchemaGetContentType, "
12045 "CT '%s' (restricting): <restriction> has no "
12046 "mandatory <simpleType>",
12047 type->name);
12048 return (-1);
12049 }
12050 } else {
12051 baseContentItem = base->contentTypeDef;
12052 if (baseContentItem == NULL) {
12053 xmlSchemaPCustomErr(ctxt,
12054 XML_SCHEMAP_INTERNAL,
12055 NULL, type, NULL,
12056 "Internal error: xmlSchemaGetContentType, "
12057 "CT '%s' (restricting), the base type has no "
12058 "content type", type->name);
12059 return (-1);
12060 }
12061 if IS_SIMPLE_TYPE(baseContentItem) {
12062 /*
12063 * 1 If the base type is a complex type whose own
12064 * {content type} is a simple type and the <restriction>
12065 * alternative is chosen
12066 */
12067 /* type->subtypes->subtypes will be the restriction item.*/
12068 res = type->subtypes->subtypes;
12069 if (res == NULL) {
12070 xmlSchemaPCustomErr(ctxt,
12071 XML_SCHEMAP_INTERNAL,
12072 NULL, type, NULL,
12073 "Internal error: xmlSchemaGetContentType, "
12074 "CT '%s' (restricting): <simpleType> has no "
12075 "<restriction>", type->name);
12076 return (-1);
12077 }
12078 /*
12079 * 1.1 the simple type definition corresponding to the
12080 * <simpleType> among the [children] of <restriction>if
12081 * there is one;
12082 */
12083 res = res->subtypes;
12084 if (res == NULL) {
12085 /*
12086 * 1.2 otherwise the {content type}
12087 * of the base type .
12088 */
12089 res = baseContentItem;
12090 }
12091 }
12092 }
12093 /*
12094 * SPECIAL TODO: If *restricting* the spec wants us to
12095 * create an *additional* simple type which restricts the
12096 * located simple type; we won't do this yet, and look how
12097 * far we get with it.
12098 */
12099 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12100 /*
12101 * Summary: a complex type (simple content) can *extend*
12102 * only a complex base with a simple type as content.
12103 */
12104 /*
12105 * 3 If the type definition ·resolved· to by the ·actual
12106 * value· of the base [attribute] is a complex type
12107 * definition (whose own {content type} *must be* a simple
12108 * type definition, see below) and the *<extension>*
12109 * alternative is chosen, then the {content type} of that
12110 * complex type definition;
12111 */
12112 res = base->contentTypeDef;
12113 if (res == NULL) {
12114 xmlSchemaPCustomErr(ctxt,
12115 XML_SCHEMAP_INTERNAL,
12116 NULL, type, NULL,
12117 "Internal error: xmlSchemaGetContentType, "
12118 "CT '%s' (extending), the base type has no content "
12119 "type", type->name);
12120 return (-1);
12121 }
12122 if (! IS_SIMPLE_TYPE(res)) {
12123 xmlSchemaPCustomErr(ctxt,
12124 XML_SCHEMAP_INTERNAL,
12125 NULL, type, NULL,
12126 "Internal error: xmlSchemaGetContentType, "
12127 "CT '%s' (extending), the content type of the "
12128 "base is not a simple type", type->name);
12129 return (-1);
12130 }
12131 }
12132 } else /* if IS_COMPLEX_TYPE(base) */
12133 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12134 /*
12135 * 4 otherwise (the type definition ·resolved· to by the
12136 * ·actual value· of the base [attribute] is a simple type
12137 * definition and the <extension> alternative is chosen),
12138 * then that simple type definition.
12139 */
12140 res = base;
12141 }
12142 type->contentTypeDef = res;
12143 if (res == NULL) {
12144 xmlSchemaPCustomErr(ctxt,
12145 XML_SCHEMAP_INTERNAL,
12146 NULL, type, NULL,
12147 "Internal error: xmlSchemaGetContentType, "
12148 "'%s', the content type could not be determined",
12149 type->name);
12150 return (-1);
12151 }
12152
12153 }
12154
12155}
12156#endif
12157
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012158/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012159 * xmlSchemaTypeFixup:
12160 * @typeDecl: the schema type definition
12161 * @ctxt: the schema parser context
12162 *
12163 * Fixes the content model of the type.
12164 */
12165static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012166xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012167 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012168{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 xmlSchemaTypePtr ctxtType;
12170
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012171 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000012172 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012173 /*
12174 * Do not allow the following types to be typefixed, prior to
12175 * the corresponding simple/complex types.
12176 */
12177 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012178 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012179 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
12180 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
12181 case XML_SCHEMA_TYPE_UNION:
12182 case XML_SCHEMA_TYPE_RESTRICTION:
12183 case XML_SCHEMA_TYPE_EXTENSION:
12184 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012185 default:
12186 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012187 }
12188 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012189 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012190 name = item->name;
12191 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
12192 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012194 if (item->subtypes != NULL) {
12195 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012196 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012197 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012198 NULL);
12199 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012200 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012201 XML_SCHEMA_CONTENT_SIMPLE;
12202 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012203 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012204 break;
12205 }
12206 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012207 xmlSchemaTypePtr base = NULL;
12208
12209 ctxt->ctxtType->flags |=
12210 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012211 if (item->baseType != NULL)
12212 base = item->baseType;
12213 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012214 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012215 xmlSchemaGetType(ctxt->schema, item->base,
12216 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012217 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012218 xmlSchemaPResCompAttrErr(ctxt,
12219 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000012220 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012221 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
12222 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012223 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012224 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000012225 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012226 xmlSchemaTypeFixup(base, ctxt, NULL);
12227 }
William M. Brack2f2a6632004-08-20 23:09:47 +000012228 }
12229 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012230 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
12231 /*
12232 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000012233 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012234 /*
12235 * Content type.
12236 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012237 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012238 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012239 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12240 else if ((item->subtypes->subtypes == NULL) &&
12241 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012242 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012243 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012244 XML_SCHEMA_TYPE_SEQUENCE)))
12245 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012246 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12247 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012248 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012249 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012250 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012251 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012252 else {
12253 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012254 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012255 XML_SCHEMA_CONTENT_ELEMENTS;
12256 }
12257 } else {
12258 /*
12259 * SimpleType restriction.
12260 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012261 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012262 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012263 break;
12264 }
12265 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012266 xmlSchemaTypePtr base = NULL;
12267 xmlSchemaContentType explicitContentType;
12268
12269 /*
12270 * An extension does exist on a complexType only.
12271 */
12272 ctxt->ctxtType->flags |=
12273 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012274 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012275 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012276 xmlSchemaPCustomErr(ctxt,
12277 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012278 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012279 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000012280 return;
12281 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012282 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012283 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012284 xmlSchemaGetType(ctxt->schema, item->base,
12285 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012286 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012287 xmlSchemaPResCompAttrErr(ctxt,
12288 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012289 NULL, item, item->node,
12290 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012291 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012292 } else if (base->contentType ==
12293 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012294 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012295 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012296 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012297 }
12298 /*
12299 * The type definition ·resolved· to by the ·actual
12300 * value· of the base [attribute]
12301 */
12302 ctxt->ctxtType->baseType = base;
12303 /*
12304 * TODO: This one is still needed for computation of
12305 * the content model by xmlSchemaBuildAContentModel.
12306 * Try to get rid of it.
12307 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012308 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012309 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012310 if ((item->subtypes != NULL) &&
12311 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
12312 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012313
12314 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012315 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012316 /* 1.1.1 */
12317 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012318 else if ((item->subtypes->subtypes == NULL) &&
12319 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012320 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012321 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012322 XML_SCHEMA_TYPE_SEQUENCE)))
12323 /* 1.1.2 */
12324 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012325 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012326 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012327 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012328 /* 1.1.3 */
12329 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
12330 if (base != NULL) {
12331 /* It will be reported later, if the base is missing. */
12332 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
12333 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012334 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012335 } else if (base->contentType ==
12336 XML_SCHEMA_CONTENT_EMPTY) {
12337 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012338 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012339 XML_SCHEMA_CONTENT_ELEMENTS;
12340 } else {
12341 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012342 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012343 XML_SCHEMA_CONTENT_ELEMENTS;
12344 }
12345 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012346 break;
12347 }
12348 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012349 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012350 ctxt->ctxtType = item;
12351 /*
12352 * Start with an empty content-type type.
12353 */
12354 if (item->subtypes == NULL)
12355 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12356
12357 if ((item->subtypes == NULL) ||
12358 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012359 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012360 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
12362 /*
12363 * This case is understood as shorthand for complex
12364 * content restricting the ur-type definition, and
12365 * the details of the mappings should be modified as
12366 * necessary.
12367 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012368 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12369 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012371 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012372 * Assume that we inherit the content-type type
12373 * from 'anyType', which is 'mixed' and a particle
12374 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 */
12376 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012377 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012378 /*
12379 * Fixup the sub components.
12380 */
12381 if ((item->subtypes != NULL) &&
12382 (item->subtypes->contentType ==
12383 XML_SCHEMA_CONTENT_UNKNOWN)) {
12384 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012385 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012386 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12387 item->contentType = XML_SCHEMA_CONTENT_MIXED;
12388 } else if (item->subtypes != NULL) {
12389 /*
12390 * Use the content-type type of the model groups
12391 * defined, if 'mixed' is not set. If 'mixed' is set
12392 * it will expand the content-type by allowing character
12393 * content to appear.
12394 */
12395 item->contentType =
12396 item->subtypes->contentType;
12397 }
12398 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012399 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012400 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012401 break;
12402 }
12403 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012404 if (item->subtypes == NULL) {
12405 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
12406 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
12407 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000012408 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012409 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012410 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
12411 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012412 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000012413 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012414 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012415 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 if (item->subtypes != NULL)
12417 item->contentType =
12418 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012419 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012420 /*
12421 * Removed due to implementation of the build of attribute uses.
12422 */
12423 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012424 if (item->attributes == NULL)
12425 item->attributes =
12426 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000012427 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012428 }
12429 break;
12430 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012431 case XML_SCHEMA_TYPE_SIMPLE:
12432 /*
12433 * Simple Type Definition Schema Component
12434 *
12435 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012436 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012437 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12438 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012439 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012440 ctxt->ctxtType = item;
12441 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012442 }
12443 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012444 if ((item->baseType != NULL) &&
12445 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012446 XML_SCHEMA_CONTENT_UNKNOWN)) {
12447 /* OPTIMIZE: Actually this one will never by hit, since
12448 * the base type is already type-fixed in <restriction>.
12449 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012450 ctxt->ctxtType = item;
12451 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012452 }
12453 /* Base type:
12454 * 2 If the <list> or <union> alternative is chosen,
12455 * then the ·simple ur-type definition·.
12456 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012457 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012458 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012459 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12460 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12461 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012462 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012463 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12464 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
12465 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000012466 XML_SCHEMA_TYPE_RESTRICTION) {
12467 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
12468
12469 /*
12470 * Variety
12471 * If the <restriction> alternative is chosen, then the
12472 * {variety} of the {base type definition}.
12473 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012474 if (item->baseType != NULL) {
12475 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012476 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012477 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
12478 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012479 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012480 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
12481 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000012482 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012483 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012484 /*
12485 * Schema Component Constraint: Simple Type Restriction
12486 * (Facets)
12487 * NOTE: Satisfaction of 1 and 2 arise from the fixup
12488 * applied beforehand.
12489 *
12490 * 3 The {facets} of R are the union of S and the {facets}
12491 * of B, eliminating duplicates. To eliminate duplicates,
12492 * when a facet of the same kind occurs in both S and the
12493 * {facets} of B, the one in the {facets} of B is not
12494 * included, with the exception of enumeration and pattern
12495 * facets, for which multiple occurrences with distinct values
12496 * are allowed.
12497 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012498 if (item->baseType->facetSet != NULL) {
12499 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012500 if (last != NULL)
12501 while (last->next != NULL)
12502 last = last->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012503 cur = item->baseType->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012504 for (; cur != NULL; cur = cur->next) {
12505 /*
12506 * Base patterns won't be add here:
12507 * they are ORed in a type and
12508 * ANDed in derived types. This will
12509 * happed at validation level by
12510 * walking the base axis of the type.
12511 */
12512 if (cur->facet->type ==
12513 XML_SCHEMA_FACET_PATTERN)
12514 continue;
12515 facet = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012516 if ((item->facetSet != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012517 (cur->facet->type !=
12518 XML_SCHEMA_FACET_PATTERN) &&
12519 (cur->facet->type !=
12520 XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012521 facet = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012522 do {
12523 if (cur->facet->type ==
12524 facet->facet->type)
12525 break;
12526 facet = facet->next;
12527 } while (facet != NULL);
12528 }
12529 if (facet == NULL) {
12530 facet = (xmlSchemaFacetLinkPtr)
12531 xmlMalloc(sizeof(xmlSchemaFacetLink));
12532 if (facet == NULL) {
12533 xmlSchemaPErrMemory(ctxt,
12534 "fixing simpleType", NULL);
12535 return;
12536 }
12537 facet->facet = cur->facet;
12538 facet->next = NULL;
12539 if (last == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012540 item->facetSet = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012541 else
12542 last->next = facet;
12543 last = facet;
12544 }
12545 }
12546 }
12547 }
12548 }
12549 /*
12550 * Check constraints.
12551 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012552 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000012553 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000012554 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012555 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012556 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012557 case XML_SCHEMA_TYPE_ALL:
12558 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012559 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012560 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012561 case XML_SCHEMA_TYPE_GROUP:
12562 /*
12563 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
12564 */
12565 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012566 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012567 xmlSchemaParseListRefFixup(item, ctxt);
12568 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 break;
12570 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012571 xmlSchemaParseUnionRefCheck(item, ctxt);
12572 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012573 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012574 case XML_SCHEMA_TYPE_BASIC:
12575 case XML_SCHEMA_TYPE_ANY:
12576 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012577 case XML_SCHEMA_TYPE_UR:
12578 case XML_SCHEMA_TYPE_ELEMENT:
12579 case XML_SCHEMA_TYPE_ATTRIBUTE:
12580 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000012581 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012582 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012583 case XML_SCHEMA_FACET_MININCLUSIVE:
12584 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12585 case XML_SCHEMA_FACET_MAXINCLUSIVE:
12586 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12587 case XML_SCHEMA_FACET_TOTALDIGITS:
12588 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12589 case XML_SCHEMA_FACET_PATTERN:
12590 case XML_SCHEMA_FACET_ENUMERATION:
12591 case XML_SCHEMA_FACET_WHITESPACE:
12592 case XML_SCHEMA_FACET_LENGTH:
12593 case XML_SCHEMA_FACET_MAXLENGTH:
12594 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012595 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12596 if (item->subtypes != NULL)
12597 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012598 break;
12599 }
12600 }
Daniel Veillard8651f532002-04-17 09:06:27 +000012601#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012602 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012603 xmlGenericError(xmlGenericErrorContext,
12604 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012605 item->node->doc->URL,
12606 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012607 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012608 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012609 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012610 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012611 case XML_SCHEMA_CONTENT_SIMPLE:
12612 xmlGenericError(xmlGenericErrorContext, "simple\n");
12613 break;
12614 case XML_SCHEMA_CONTENT_ELEMENTS:
12615 xmlGenericError(xmlGenericErrorContext, "elements\n");
12616 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012617 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012618 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
12619 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012620 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012621 xmlGenericError(xmlGenericErrorContext, "empty\n");
12622 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012623 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012624 xmlGenericError(xmlGenericErrorContext, "mixed\n");
12625 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012626 /* Removed, since not used. */
12627 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000012628 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012629 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
12630 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012631 */
Daniel Veillard8651f532002-04-17 09:06:27 +000012632 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012633 xmlGenericError(xmlGenericErrorContext, "basic\n");
12634 break;
12635 default:
12636 xmlGenericError(xmlGenericErrorContext,
12637 "not registered !!!\n");
12638 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000012639 }
12640#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000012641}
12642
12643/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012644 * xmlSchemaCheckFacet:
12645 * @facet: the facet
12646 * @typeDecl: the schema type definition
12647 * @ctxt: the schema parser context or NULL
12648 * @name: name of the type
12649 *
12650 * Checks the default values types, especially for facets
12651 *
12652 * Returns 0 if okay or -1 in cae of error
12653 */
12654int
12655xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012656 xmlSchemaTypePtr typeDecl,
12657 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012658{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012659 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012660 int ret = 0, reuseValCtxt = 0;
12661
Daniel Veillardce682bc2004-11-05 17:22:25 +000012662 if ((facet == NULL) || (typeDecl == NULL))
12663 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012664 /*
12665 * TODO: will the parser context be given if used from
12666 * the relaxNG module?
12667 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012668
12669 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012670 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000012671 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012672 }
12673 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012674 case XML_SCHEMA_FACET_MININCLUSIVE:
12675 case XML_SCHEMA_FACET_MINEXCLUSIVE:
12676 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012677 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
12678 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012679 /*
12680 * Okay we need to validate the value
12681 * at that point.
12682 */
12683 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012684 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012685
12686 /* 4.3.5.5 Constraints on enumeration Schema Components
12687 * Schema Component Constraint: enumeration valid restriction
12688 * It is an ·error· if any member of {value} is not in the
12689 * ·value space· of {base type definition}.
12690 *
12691 * minInclusive, maxInclusive, minExclusive, maxExclusive:
12692 * The value ·must· be in the
12693 * ·value space· of the ·base type·.
12694 */
12695 /*
12696 * This function is intended to deliver a compiled value
12697 * on the facet. In XML Schemas the type holding a facet,
12698 * cannot be a built-in type. Thus to ensure that other API
12699 * calls (relaxng) do work, if the given type is a built-in
12700 * type, we will assume that the given built-in type *is
12701 * already* the base type.
12702 */
12703 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
12704 base = typeDecl->baseType;
12705 if (base == NULL) {
12706 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012707 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012708 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012710 typeDecl->name, NULL);
12711 return (-1);
12712 }
12713 } else
12714 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012715 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012716 * This avoids perseverative creation of the
12717 * validation context if a parser context is
12718 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012719 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012720 if (ctxt != NULL) {
12721 reuseValCtxt = 1;
12722 if (ctxt->vctxt == NULL) {
12723 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
12724 return (-1);
12725 }
12726 vctxt = ctxt->vctxt;
12727 } else {
12728 vctxt = xmlSchemaNewValidCtxt(NULL);
12729 if (vctxt == NULL) {
12730 xmlSchemaPErr(ctxt, typeDecl->node,
12731 XML_SCHEMAP_INTERNAL,
12732 "Internal error: xmlSchemaCheckFacet, "
12733 "creating a new validation context.\n",
12734 NULL, NULL);
12735 return (-1);
12736 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012737 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012738
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012739 vctxt->node = facet->node;
12740 vctxt->cur = NULL;
12741 /*
12742 * NOTE: This call does not check the content nodes,
12743 * since they are not available:
12744 * facet->node is just the node holding the facet
12745 * definition, *not* the attribute holding the *value*
12746 * of the facet.
12747 */
12748 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
12749 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012750 facet->val = vctxt->value;
12751 vctxt->value = NULL;
12752 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012753 /* error code */
12754 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012755 xmlSchemaPErrExt(ctxt, facet->node,
12756 XML_SCHEMAP_INVALID_FACET,
12757 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012758 "Type definition '%s': The value '%s' of the "
12759 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012760 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012761 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012762 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012763 }
12764 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012765 } else if (ret < 0) {
12766 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012767 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012768 NULL, NULL, NULL,
12769 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012770 "failed to validate the value '%s' name of the "
12771 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000012772 facet->value,
12773 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
12774 base->name, NULL, NULL);
12775 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012776 }
12777 if (reuseValCtxt == 0)
12778 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012779 break;
12780 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012781 case XML_SCHEMA_FACET_PATTERN:
12782 facet->regexp = xmlRegexpCompile(facet->value);
12783 if (facet->regexp == NULL) {
12784 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012785 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012786 "Type definition '%s': The value '%s' of the "
12787 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012788 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012789 ret = -1;
12790 }
12791 break;
12792 case XML_SCHEMA_FACET_TOTALDIGITS:
12793 case XML_SCHEMA_FACET_FRACTIONDIGITS:
12794 case XML_SCHEMA_FACET_LENGTH:
12795 case XML_SCHEMA_FACET_MAXLENGTH:
12796 case XML_SCHEMA_FACET_MINLENGTH:{
12797 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012798
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012799 tmp =
12800 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
12801 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000012802 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012803 if (tmp != 0) {
12804 /* error code */
12805 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012806 xmlSchemaPErrExt(ctxt, facet->node,
12807 XML_SCHEMAP_INVALID_FACET_VALUE,
12808 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012809 "Type definition '%s': The value '%s' of the "
12810 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012811 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012812 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000012813 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012814 }
12815 ret = -1;
12816 }
12817 break;
12818 }
12819 case XML_SCHEMA_FACET_WHITESPACE:{
12820 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
12821 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
12822 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
12823 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
12824 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
12825 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
12826 } else {
12827 if (ctxt != NULL) {
12828 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012829 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012830 "Type definition '%s': The value '%s' of the "
12831 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012832 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012833 }
12834 ret = -1;
12835 }
12836 }
12837 default:
12838 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012839 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012840 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000012841}
12842
12843/**
Daniel Veillard4255d502002-04-16 15:50:10 +000012844 * xmlSchemaCheckDefaults:
12845 * @typeDecl: the schema type definition
12846 * @ctxt: the schema parser context
12847 *
12848 * Checks the default values types, especially for facets
12849 */
12850static void
12851xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012852 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000012853{
Daniel Veillard4255d502002-04-16 15:50:10 +000012854 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012855 name = typeDecl->name;
12856 /*
12857 * NOTE: It is intended to use the facets list, instead
12858 * of facetSet.
12859 */
12860 if (typeDecl->facets != NULL) {
12861 xmlSchemaFacetPtr facet = typeDecl->facets;
12862
12863 while (facet != NULL) {
12864 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
12865 facet = facet->next;
12866 }
12867 }
Daniel Veillard4255d502002-04-16 15:50:10 +000012868}
12869
12870/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012871 * xmlSchemaGetCircModelGrDefRef:
12872 * @ctxtGr: the searched model group
12873 * @list: the list of model groups to be processed
12874 *
12875 * This one is intended to be used by
12876 * xmlSchemaCheckGroupDefCircular only.
12877 *
12878 * Returns the circular model group definition reference, otherwise NULL.
12879 */
12880static xmlSchemaTypePtr
12881xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
12882 xmlSchemaTypePtr gr)
12883{
12884 xmlSchemaTypePtr circ = NULL;
12885 int marked;
12886 /*
12887 * We will search for an model group reference which
12888 * references the context model group definition.
12889 */
12890 while (gr != NULL) {
12891 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
12892 (gr->type == XML_SCHEMA_TYPE_ALL) ||
12893 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
12894 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
12895 (gr->subtypes != NULL)) {
12896 marked = 0;
12897 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
12898 (gr->ref != NULL)) {
12899 if (gr->subtypes == ctxtGrDef)
12900 return (gr);
12901 else if (gr->subtypes->flags &
12902 XML_SCHEMAS_TYPE_MARKED) {
12903 gr = gr->next;
12904 continue;
12905 } else {
12906 /*
12907 * Mark to avoid infinite recursion on
12908 * circular references not yet examined.
12909 */
12910 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
12911 marked = 1;
12912 }
12913 if (gr->subtypes->subtypes != NULL)
12914 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12915 gr->subtypes->subtypes);
12916 /*
12917 * Unmark the visited model group definition.
12918 */
12919 if (marked)
12920 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
12921 if (circ != NULL)
12922 return (circ);
12923 } else {
12924 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
12925 (xmlSchemaTypePtr) gr->subtypes);
12926 if (circ != NULL)
12927 return (circ);
12928 }
12929
12930 }
12931 gr = gr->next;
12932 }
12933 return (NULL);
12934}
12935
12936/**
12937 * xmlSchemaCheckGroupDefCircular:
12938 * attrGr: the model group definition
12939 * @ctxt: the parser context
12940 * @name: the name
12941 *
12942 * Checks for circular references to model group definitions.
12943 */
12944static void
12945xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
12946 xmlSchemaParserCtxtPtr ctxt,
12947 const xmlChar * name ATTRIBUTE_UNUSED)
12948{
12949 /*
12950 * Schema Component Constraint: Model Group Correct
12951 * 2 Circular groups are disallowed. That is, within the {particles}
12952 * of a group there must not be at any depth a particle whose {term}
12953 * is the group itself.
12954 */
12955 /*
12956 * NOTE: "gr->subtypes" holds the referenced group.
12957 */
12958 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
12959 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
12960 (modelGrDef->subtypes == NULL))
12961 return;
12962 else {
12963 xmlSchemaTypePtr circ;
12964
12965 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
12966 if (circ != NULL) {
12967 /*
12968 * TODO: Report the referenced attr group as QName.
12969 */
12970 xmlSchemaPCustomErr(ctxt,
12971 XML_SCHEMAP_MG_PROPS_CORRECT_2,
12972 NULL, NULL, circ->node,
12973 "Circular reference to the model group definition '%s' "
12974 "defined", modelGrDef->name);
12975 /*
12976 * NOTE: We will cut the reference to avoid further
12977 * confusion of the processor.
12978 * TODO: SPEC: Does the spec define how to process here?
12979 */
12980 circ->subtypes = NULL;
12981 }
12982 }
12983}
12984
12985
12986/**
12987 * xmlSchemaGetCircAttrGrRef:
12988 * @ctxtGr: the searched attribute group
12989 * @attr: the current attribute list to be processed
12990 *
12991 * This one is intended to be used by
12992 * xmlSchemaCheckSRCAttributeGroupCircular only.
12993 *
12994 * Returns the circular attribute grou reference, otherwise NULL.
12995 */
12996static xmlSchemaAttributeGroupPtr
12997xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
12998 xmlSchemaAttributePtr attr)
12999{
13000 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13001 int marked;
13002 /*
13003 * We will search for an attribute group reference which
13004 * references the context attribute group.
13005 */
13006 while (attr != NULL) {
13007 marked = 0;
13008 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13009 gr = (xmlSchemaAttributeGroupPtr) attr;
13010 if (gr->refItem != NULL) {
13011 if (gr->refItem == ctxtGr)
13012 return (gr);
13013 else if (gr->refItem->flags &
13014 XML_SCHEMAS_ATTRGROUP_MARKED) {
13015 attr = attr->next;
13016 continue;
13017 } else {
13018 /*
13019 * Mark as visited to avoid infinite recursion on
13020 * circular references not yet examined.
13021 */
13022 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13023 marked = 1;
13024 }
13025 }
13026 if (gr->attributes != NULL)
13027 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13028 /*
13029 * Unmark the visited group's attributes.
13030 */
13031 if (marked)
13032 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13033 if (circ != NULL)
13034 return (circ);
13035 }
13036 attr = attr->next;
13037 }
13038 return (NULL);
13039}
13040
13041/**
13042 * xmlSchemaCheckSRCAttributeGroupCircular:
13043 * attrGr: the attribute group definition
13044 * @ctxt: the parser context
13045 * @name: the name
13046 *
13047 * Checks for circular references of attribute groups.
13048 */
13049static void
13050xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13051 xmlSchemaParserCtxtPtr ctxt,
13052 const xmlChar * name ATTRIBUTE_UNUSED)
13053{
13054 /*
13055 * Schema Representation Constraint:
13056 * Attribute Group Definition Representation OK
13057 * 3 Circular group reference is disallowed outside <redefine>.
13058 * That is, unless this element information item's parent is
13059 * <redefine>, then among the [children], if any, there must
13060 * not be an <attributeGroup> with ref [attribute] which resolves
13061 * to the component corresponding to this <attributeGroup>. Indirect
13062 * circularity is also ruled out. That is, when QName resolution
13063 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13064 * any <attributeGroup>s with a ref [attribute] among the [children],
13065 * it must not be the case that a ·QName· is encountered at any depth
13066 * which resolves to the component corresponding to this <attributeGroup>.
13067 */
13068 /*
13069 * Only global components can be referenced.
13070 */
13071 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
13072 (attrGr->attributes == NULL))
13073 return;
13074 else {
13075 xmlSchemaAttributeGroupPtr circ;
13076
13077 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
13078 if (circ != NULL) {
13079 /*
13080 * TODO: Report the referenced attr group as QName.
13081 */
13082 xmlSchemaPCustomErr(ctxt,
13083 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
13084 NULL, NULL, circ->node,
13085 "Circular reference to the attribute group '%s' "
13086 "defined", attrGr->name);
13087 /*
13088 * NOTE: We will cut the reference to avoid further
13089 * confusion of the processor.
13090 * BADSPEC: The spec should define how to process in this case.
13091 */
13092 circ->attributes = NULL;
13093 circ->refItem = NULL;
13094 }
13095 }
13096}
13097
13098/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000013099 * xmlSchemaAttrGrpFixup:
13100 * @attrgrpDecl: the schema attribute definition
13101 * @ctxt: the schema parser context
13102 * @name: the attribute name
13103 *
13104 * Fixes finish doing the computations on the attributes definitions
13105 */
13106static void
Daniel Veillard3646d642004-06-02 19:19:14 +000013107xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013108 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000013109{
13110 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000013111 name = attrgrp->name;
13112 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013113 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000013114 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013115 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000013116
Daniel Veillardc0826a72004-08-10 14:17:33 +000013117 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
13118 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013119 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013120 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013121 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013122 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
13123 "ref", attrgrp->ref, attrgrp->refNs,
13124 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013125 return;
13126 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013127 attrgrp->refItem = ref;
13128 /*
13129 * Check for self reference!
13130 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013131 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013132 attrgrp->attributes = ref->attributes;
13133 attrgrp->attributeWildcard = ref->attributeWildcard;
13134 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000013135}
13136
13137/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013138 * xmlSchemaAttrCheckValConstr:
13139 * @item: an schema attribute declaration/use
13140 * @ctxt: a schema parser context
13141 * @name: the name of the attribute
13142 *
13143 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000013144 *
13145 * Fixes finish doing the computations on the attributes definitions
13146 */
13147static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013148xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
13149 xmlSchemaParserCtxtPtr ctxt,
13150 const xmlChar * name ATTRIBUTE_UNUSED)
13151{
13152
13153 /*
13154 * a-props-correct
13155 * Schema Component Constraint: Attribute Declaration Properties Correct
13156 *
13157 * 2 if there is a {value constraint}, the canonical lexical
13158 * representation of its value must be ·valid· with respect
13159 * to the {type definition} as defined in String Valid (§3.14.4).
13160 */
13161
13162 if (item->defValue != NULL) {
13163 int ret;
13164 xmlNodePtr node;
13165 xmlSchemaTypePtr type;
13166
13167 if (item->subtypes == NULL) {
13168 xmlSchemaPErr(ctxt, item->node,
13169 XML_SCHEMAP_INTERNAL,
13170 "Internal error: xmlSchemaCheckAttrValConstr, "
13171 "type is missing... skipping validation of "
13172 "value constraint", NULL, NULL);
13173 return;
13174 }
13175
13176 /*
13177 * TODO: Try to avoid creating a new context.
13178 * TODO: This all is not very performant.
13179 */
13180 type = item->subtypes;
13181 /*
13182 * Ensure there's validation context.
13183 */
13184 if (ctxt->vctxt == NULL) {
13185 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
13186 xmlSchemaPErr(ctxt, item->node,
13187 XML_SCHEMAP_INTERNAL,
13188 "Internal error: xmlSchemaCheckAttrValConstr, "
13189 "creating a new validation context.\n",
13190 NULL, NULL);
13191 return;
13192 }
13193 }
13194
13195 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13196 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
13197 else
13198 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
13199 ctxt->vctxt->node = node;
13200 ctxt->vctxt->cur = NULL;
13201 /*
13202 * NOTE: This call does not check the content nodes,
13203 * since they are not available:
13204 * facet->node is just the node holding the facet
13205 * definition, *not* the attribute holding the *value*
13206 * of the facet.
13207 */
13208 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
13209 item->defValue, 0, 1, 1, 0);
13210 if (ret == 0) {
13211 /*
13212 * Store the computed value.
13213 */
13214 item->defVal = ctxt->vctxt->value;
13215 ctxt->vctxt->value = NULL;
13216 } else if (ret > 0) {
13217 if (ctxt != NULL) {
13218 xmlSchemaPSimpleTypeErr(ctxt,
13219 XML_SCHEMAP_A_PROPS_CORRECT_2,
13220 NULL, NULL, node,
13221 type, NULL, item->defValue,
13222 NULL, NULL, NULL);
13223 }
13224 } else if (ret < 0) {
13225 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13226 NULL, NULL, node,
13227 "Internal error: xmlSchemaAttrCheckValConstr, "
13228 "failed to validate the value constraint of the "
13229 "attribute decl/use against the type '%s'",
13230 type->name);
13231 }
13232 }
13233}
13234
13235#if 0 /* Not used yet. */
13236static int
13237xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13238 xmlSchemaElementPtr edecl)
13239{
13240 /*
13241 * TODO: 1 The values of the properties of an element declaration must be as
13242 * described in the property tableau in The Element Declaration Schema
13243 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
13244 */
13245 /*
13246 * 2 If there is a {value constraint}, the canonical lexical
13247 * representation of its value must be ·valid· with respect to the {type
13248 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13249 *
13250 * NOTE: This is done in xmlSchemaCheckElemValConstr.
13251 */
13252 /*
13253 * 3 If there is a non-·absent· {substitution group affiliation},
13254 * then {scope} must be global.
13255 *
13256 * NOTE: This is done in xmlSchemaParseElement.
13257 * TODO: Move it to this layer here.
13258 */
13259 /*
13260 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
13261 * of the element declaration must be validly derived from the {type
13262 * definition} of the {substitution group affiliation}, given the value
13263 * of the {substitution group exclusions} of the {substitution group
13264 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
13265 * (if the {type definition} is complex) or as defined in
13266 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
13267 * simple).
13268 */
13269 /*
13270 * TODO: 5 If the {type definition} or {type definition}'s {content type}
13271 * is or is derived from ID then there must not be a {value constraint}.
13272 * Note: The use of ID as a type definition for elements goes beyond
13273 * XML 1.0, and should be avoided if backwards compatibility is desired
13274 */
13275 /*
13276 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
13277 * be possible to return to an element declaration by repeatedly following
13278 * the {substitution group affiliation} property.
13279 */
13280}
13281#endif
13282
13283/**
13284 * xmlSchemaCheckElemValConstr:
13285 * @item: an schema element declaration/particle
13286 * @ctxt: a schema parser context
13287 * @name: the name of the attribute
13288 *
13289 * Validates the value constraints of an element declaration.
13290 *
13291 * Fixes finish doing the computations on the element declarations.
13292 */
13293static void
13294xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
13295 xmlSchemaParserCtxtPtr ctxt,
13296 const xmlChar * name ATTRIBUTE_UNUSED)
13297{
13298 if (decl->value != NULL) {
13299 int ret;
13300 xmlNodePtr node = NULL;
13301 xmlSchemaTypePtr type;
13302
13303 /*
13304 * 2 If there is a {value constraint}, the canonical lexical
13305 * representation of its value must be ·valid· with respect to the {type
13306 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
13307 */
13308 if (decl->subtypes == NULL) {
13309 xmlSchemaPErr(ctxt, decl->node,
13310 XML_SCHEMAP_INTERNAL,
13311 "Internal error: xmlSchemaCheckElemValConstr, "
13312 "type is missing... skipping validation of "
13313 "the value constraint", NULL, NULL);
13314 return;
13315 }
13316 /*
13317 * Ensure there's a validation context.
13318 */
13319 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13320 return;
13321
13322 type = decl->subtypes;
13323
13324 if (decl->node != NULL) {
13325 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
13326 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
13327 else
13328 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
13329 }
13330 ctxt->vctxt->node = node;
13331 ctxt->vctxt->cur = NULL;
13332 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
13333 node);
13334 if (ret == 0) {
13335 /*
13336 * Consume the computed value.
13337 */
13338 decl->defVal = ctxt->vctxt->value;
13339 ctxt->vctxt->value = NULL;
13340 } else if (ret < 0) {
13341 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13342 NULL, NULL, node,
13343 "Internal error: xmlSchemaElemCheckValConstr, "
13344 "failed to validate the value constraint of the "
13345 "element declaration '%s'",
13346 decl->name);
13347 }
13348 }
13349}
13350
13351/**
13352 * xmlSchemaAttrFixup:
13353 * @item: an schema attribute declaration/use.
13354 * @ctxt: a schema parser context
13355 * @name: the name of the attribute
13356 *
13357 * Fixes finish doing the computations on attribute declarations/uses.
13358 */
13359static void
13360xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
13361 xmlSchemaParserCtxtPtr ctxt,
13362 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000013363{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013364 /*
13365 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013366 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000013367 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013368 /*
13369 * The simple type definition corresponding to the <simpleType> element
13370 * information item in the [children], if present, otherwise the simple
13371 * type definition ·resolved· to by the ·actual value· of the type
13372 * [attribute], if present, otherwise the ·simple ur-type definition·.
13373 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013374 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013375 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013376 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
13377 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013378 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013379 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013380 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000013381
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013382 type = xmlSchemaGetType(ctxt->schema, item->typeName,
13383 item->typeNs);
13384 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013385 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013386 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013387 NULL, (xmlSchemaTypePtr) item, item->node,
13388 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013389 XML_SCHEMA_TYPE_SIMPLE, NULL);
13390 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013391 item->subtypes = type;
13392
13393 } else if (item->ref != NULL) {
13394 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000013395
Daniel Veillardc0826a72004-08-10 14:17:33 +000013396 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013397 * We have an attribute use here; assign the referenced
13398 * attribute declaration.
13399 */
13400 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013401 * TODO: Evaluate, what errors could occur if the declaration is not
13402 * found. It might be possible that the "typefixup" might crash if
13403 * no ref declaration was found.
13404 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013405 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
13406 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013407 xmlSchemaPResCompAttrErr(ctxt,
13408 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013409 NULL, (xmlSchemaTypePtr) item, item->node,
13410 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013411 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013412 return;
13413 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013414 item->refDecl = decl;
13415 xmlSchemaAttrFixup(decl, ctxt, NULL);
13416
13417 item->subtypes = decl->subtypes;
13418 /*
13419 * Attribute Use Correct
13420 * au-props-correct.2: If the {attribute declaration} has a fixed
13421 * {value constraint}, then if the attribute use itself has a
13422 * {value constraint}, it must also be fixed and its value must match
13423 * that of the {attribute declaration}'s {value constraint}.
13424 */
13425 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
13426 (item->defValue != NULL)) {
13427 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
13428 (!xmlStrEqual(item->defValue, decl->defValue))) {
13429 xmlSchemaPCustomErr(ctxt,
13430 XML_SCHEMAP_AU_PROPS_CORRECT_2,
13431 NULL, NULL, item->node,
13432 "The value constraint must be fixed "
13433 "and match the referenced attribute "
13434 "declarations's value constraint '%s'",
13435 decl->defValue);
13436 }
13437 /*
13438 * FUTURE: One should change the values of the attr. use
13439 * if ever validation should be attempted even if the
13440 * schema itself was not fully valid.
13441 */
13442 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013443 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013444 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13445 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013446}
13447
13448/**
13449 * xmlSchemaParse:
13450 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013451 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013452 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000013453 * XML Shema struture which can be used to validate instances.
13454 * *WARNING* this interface is highly subject to change
13455 *
13456 * Returns the internal XML Schema structure built from the resource or
13457 * NULL in case of error
13458 */
13459xmlSchemaPtr
13460xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
13461{
13462 xmlSchemaPtr ret = NULL;
13463 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013464 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013465 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013466
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013467 /*
13468 * This one is used if the schema to be parsed was specified via
13469 * the API; i.e. not automatically by the validated instance document.
13470 */
13471
Daniel Veillard4255d502002-04-16 15:50:10 +000013472 xmlSchemaInitTypes();
13473
Daniel Veillard6045c902002-10-09 21:13:59 +000013474 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000013475 return (NULL);
13476
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013477 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000013478 ctxt->counter = 0;
13479 ctxt->container = NULL;
13480
13481 /*
13482 * First step is to parse the input document into an DOM/Infoset
13483 */
Daniel Veillard6045c902002-10-09 21:13:59 +000013484 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013485 doc = xmlReadFile((const char *) ctxt->URL, NULL,
13486 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013487 if (doc == NULL) {
13488 xmlSchemaPErr(ctxt, NULL,
13489 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013490 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013491 ctxt->URL, NULL);
13492 return (NULL);
13493 }
Daniel Veillard6045c902002-10-09 21:13:59 +000013494 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013495 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
13496 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013497 if (doc == NULL) {
13498 xmlSchemaPErr(ctxt, NULL,
13499 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013500 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013501 NULL, NULL);
13502 return (NULL);
13503 }
13504 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000013505 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000013506 } else if (ctxt->doc != NULL) {
13507 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013508 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000013509 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013510 xmlSchemaPErr(ctxt, NULL,
13511 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013512 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013513 NULL, NULL);
13514 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000013515 }
13516
13517 /*
13518 * Then extract the root and Schema parse it
13519 */
13520 root = xmlDocGetRootElement(doc);
13521 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013522 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
13523 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013524 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000013525 if (!preserve) {
13526 xmlFreeDoc(doc);
13527 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013528 return (NULL);
13529 }
13530
13531 /*
13532 * Remove all the blank text nodes
13533 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000013534 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000013535
13536 /*
13537 * Then do the parsing for good
13538 */
13539 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000013540 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000013541 if (!preserve) {
13542 xmlFreeDoc(doc);
13543 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013544 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000013545 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013546 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000013547 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000013548 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013549 ctxt->ctxtType = NULL;
13550 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000013551 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000013552 * Then fixup all attributes declarations
13553 */
13554 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
13555
13556 /*
13557 * Then fixup all attributes group declarations
13558 */
13559 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
13560 ctxt);
13561
13562 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013563 * Check attribute groups for circular references.
13564 */
13565 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
13566 xmlSchemaCheckAttributeGroupCircular, ctxt);
13567
13568 /*
13569 * Then fixup all model group definitions.
13570 */
13571 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013572
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013573 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000013574 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000013575 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013576 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013577
13578 /*
13579 * Then fix references of element declaration; apply constraints.
13580 */
13581 xmlHashScanFull(ret->elemDecl,
13582 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013583
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013584 /*
13585 * Check model groups defnitions for circular references.
13586 */
13587 xmlHashScan(ret->groupDecl, (xmlHashScanner)
13588 xmlSchemaCheckGroupDefCircular, ctxt);
13589
Daniel Veillard4255d502002-04-16 15:50:10 +000013590 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013591 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000013592 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013593 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013594 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000013595
13596 /*
13597 * Then check the defaults part of the type like facets values
13598 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013599 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000013600
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013601 /*
13602 * Validate the value constraint of attribute declarations/uses.
13603 */
13604 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
13605
13606 /*
13607 * Validate the value constraint of element declarations.
13608 */
13609 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
13610
Daniel Veillardc0826a72004-08-10 14:17:33 +000013611
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013612 if (ctxt->nberrors != 0) {
13613 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013614 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000013615 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013616 return (ret);
13617}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013618
Daniel Veillard4255d502002-04-16 15:50:10 +000013619/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000013620 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000013621 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000013622 * @err: the error callback
13623 * @warn: the warning callback
13624 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000013625 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000013626 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000013627 */
13628void
13629xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013630 xmlSchemaValidityErrorFunc err,
13631 xmlSchemaValidityWarningFunc warn, void *ctx)
13632{
Daniel Veillard4255d502002-04-16 15:50:10 +000013633 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000013635 ctxt->error = err;
13636 ctxt->warning = warn;
13637 ctxt->userData = ctx;
13638}
13639
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013640/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000013641 * xmlSchemaGetParserErrors:
13642 * @ctxt: a XMl-Schema parser context
13643 * @err: the error callback result
13644 * @warn: the warning callback result
13645 * @ctx: contextual data for the callbacks result
13646 *
13647 * Get the callback information used to handle errors for a parser context
13648 *
13649 * Returns -1 in case of failure, 0 otherwise
13650 */
13651int
13652xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
13653 xmlSchemaValidityErrorFunc * err,
13654 xmlSchemaValidityWarningFunc * warn, void **ctx)
13655{
13656 if (ctxt == NULL)
13657 return(-1);
13658 if (err != NULL)
13659 *err = ctxt->error;
13660 if (warn != NULL)
13661 *warn = ctxt->warning;
13662 if (ctx != NULL)
13663 *ctx = ctxt->userData;
13664 return(0);
13665}
13666
13667/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013668 * xmlSchemaFacetTypeToString:
13669 * @type: the facet type
13670 *
13671 * Convert the xmlSchemaTypeType to a char string.
13672 *
13673 * Returns the char string representation of the facet type if the
13674 * type is a facet and an "Internal Error" string otherwise.
13675 */
13676static const char *
13677xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
13678{
13679 switch (type) {
13680 case XML_SCHEMA_FACET_PATTERN:
13681 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013682 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013683 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013684 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013685 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013686 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013687 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013688 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013689 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013690 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013691 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013692 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013693 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013694 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013695 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013696 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013697 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013698 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013699 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013700 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013701 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013702 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013703 return ("fractionDigits");
13704 default:
13705 break;
13706 }
13707 return ("Internal Error");
13708}
13709
Daniel Veillardc0826a72004-08-10 14:17:33 +000013710
Daniel Veillardc0826a72004-08-10 14:17:33 +000013711
13712static int
13713xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
13714{
13715 xmlSchemaTypePtr anc;
13716
13717 /*
13718 * The normalization type can be changed only for types which are derived
13719 * from xsd:string.
13720 */
13721 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013722 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013723 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000013724 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
13725 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000013726 else {
13727 /*
13728 * For all ·atomic· datatypes other than string (and types ·derived·
13729 * by ·restriction· from it) the value of whiteSpace is fixed to
13730 * collapse
13731 */
13732 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13733 }
13734 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13735 /*
13736 * For list types the facet "whiteSpace" is fixed to "collapse".
13737 */
13738 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13739 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13740 return (-1);
13741 } else if (type->facetSet != NULL) {
13742 xmlSchemaTypePtr anyST;
13743 xmlSchemaFacetLinkPtr lin;
13744
13745 /*
13746 * Atomic types.
13747 */
13748 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13749 anc = type->baseType;
13750 do {
13751 /*
13752 * For all ·atomic· datatypes other than string (and types ·derived·
13753 * by ·restriction· from it) the value of whiteSpace is fixed to
13754 * collapse
13755 */
13756 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
13757 (anc->builtInType == XML_SCHEMAS_STRING)) {
13758
13759 lin = type->facetSet;
13760 do {
13761 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
13762 if (lin->facet->whitespace ==
13763 XML_SCHEMAS_FACET_COLLAPSE) {
13764 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13765 } else if (lin->facet->whitespace ==
13766 XML_SCHEMAS_FACET_REPLACE) {
13767 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
13768 } else
13769 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
13770 break;
13771 }
13772 lin = lin->next;
13773 } while (lin != NULL);
13774 break;
13775 }
13776 anc = anc->baseType;
13777 } while (anc != anyST);
13778 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
13779 }
13780 return (-1);
13781}
13782
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013783/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000013784 * xmlSchemaValidateFacetsInternal:
13785 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000013787 * @facets: the list of facets to check
13788 * @value: the lexical repr of the value to validate
13789 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000013790 * @fireErrors: if 0, only internal errors will be fired;
13791 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000013792 *
13793 * Check a value against all facet conditions
13794 *
13795 * Returns 0 if the element is schemas valid, a positive error code
13796 * number otherwise and -1 in case of internal or API error.
13797 */
13798static int
13799xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013800 xmlSchemaTypePtr type,
13801 const xmlChar * value,
13802 unsigned long length,
13803 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000013804{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013805 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013806 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013807 xmlSchemaTypePtr biType; /* The build-in type. */
13808 xmlSchemaTypePtr tmpType;
13809 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000013810 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013811 xmlSchemaFacetPtr facet;
13812 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013813
Daniel Veillardc0826a72004-08-10 14:17:33 +000013814#ifdef DEBUG_UNION_VALIDATION
13815 printf("Facets of type: '%s'\n", (const char *) type->name);
13816 printf(" fireErrors: %d\n", fireErrors);
13817#endif
13818
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013819 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013820 /*
13821 * NOTE: Do not jump away, if the facetSet of the given type is
13822 * empty: until now, "pattern" facets of the *base types* need to
13823 * be checked as well.
13824 */
13825 biType = type->baseType;
13826 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
13827 biType = biType->baseType;
13828 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013829 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013830 "Internal error: xmlSchemaValidateFacetsInternal, "
13831 "the base type axis of the given type '%s' does not resolve to "
13832 "a built-in type.\n",
13833 type->name, NULL);
13834 return (-1);
13835 }
13836
13837 if (type->facetSet != NULL) {
13838 facetLink = type->facetSet;
13839 while (facetLink != NULL) {
13840 facet = facetLink->facet;
13841 /*
13842 * Skip the pattern "whiteSpace": it is used to
13843 * format the character content beforehand.
13844 */
13845 switch (facet->type) {
13846 case XML_SCHEMA_FACET_WHITESPACE:
13847 case XML_SCHEMA_FACET_PATTERN:
13848 case XML_SCHEMA_FACET_ENUMERATION:
13849 break;
13850 case XML_SCHEMA_FACET_LENGTH:
13851 case XML_SCHEMA_FACET_MINLENGTH:
13852 case XML_SCHEMA_FACET_MAXLENGTH:
13853 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13854 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
13855 value, length, 0);
13856 len = length;
13857 } else
13858 ret = xmlSchemaValidateLengthFacet(biType, facet,
13859 value, ctxt->value, &len);
13860 break;
13861 default:
13862 ret = xmlSchemaValidateFacet(biType, facet, value,
13863 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013865 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013866 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013867 "Internal error: xmlSchemaValidateFacetsInternal, "
13868 "validating facet of type '%s'.\n",
13869 type->name, NULL);
13870 break;
13871 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013872 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013873 type, facet, NULL, NULL, NULL, NULL);
13874 }
13875
13876 facetLink = facetLink->next;
13877 }
13878 if (ret >= 0) {
13879 /*
13880 * Process enumerations.
13881 */
13882 retFacet = 0;
13883 facetLink = type->facetSet;
13884 while (facetLink != NULL) {
13885 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
13886 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13887 value, ctxt->value);
13888 if (retFacet <= 0)
13889 break;
13890 }
13891 facetLink = facetLink->next;
13892 }
13893 if (retFacet > 0) {
13894 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
13895 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013896 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013897 value, 0, type, NULL, NULL, NULL, NULL, NULL);
13898 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013899 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013900 "Internal error: xmlSchemaValidateFacetsInternal, "
13901 "validating facet of type '%s'.\n",
13902 BAD_CAST "enumeration", NULL);
13903 ret = -1;
13904 }
13905 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013906 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013907 if (ret >= 0) {
13908 /*
13909 * Process patters. Pattern facets are ORed at type level
13910 * and ANDed if derived. Walk the base type axis.
13911 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013912 tmpType = type;
13913 facet = NULL;
13914 do {
13915 retFacet = 0;
13916 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013917 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
13919 continue;
13920 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
13921 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013922 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013923 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013924 else if (retFacet < 0) {
13925 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
13926 "Internal error: xmlSchemaValidateFacetsInternal, "
13927 "validating 'pattern' facet '%s' of type '%s'.\n",
13928 facetLink->facet->value, tmpType->name);
13929 ret = -1;
13930 break;
13931 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000013932 /* Save the last non-validating facet. */
13933 facet = facetLink->facet;
13934 }
13935 if (retFacet != 0)
13936 break;
13937 tmpType = tmpType->baseType;
13938 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013939 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013940 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
13941 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013942 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013943 NULL, NULL, NULL, NULL);
13944 }
13945 }
13946 }
13947
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000013948 return (ret);
13949}
13950
Daniel Veillard4255d502002-04-16 15:50:10 +000013951/************************************************************************
13952 * *
13953 * Simple type validation *
13954 * *
13955 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000013956
Daniel Veillard4255d502002-04-16 15:50:10 +000013957
13958/************************************************************************
13959 * *
13960 * DOM Validation code *
13961 * *
13962 ************************************************************************/
13963
Daniel Veillard4255d502002-04-16 15:50:10 +000013964static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013965 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000013966 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013967static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013968 xmlSchemaTypePtr type,
13969 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000013970
Daniel Veillard3646d642004-06-02 19:19:14 +000013971
13972/**
13973 * xmlSchemaFreeAttrStates:
13974 * @state: a list of attribute states
13975 *
13976 * Free the given list of attribute states
13977 *
13978 */
13979static void
13980xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
13981{
13982 xmlSchemaAttrStatePtr tmp;
13983 while (state != NULL) {
13984 tmp = state;
13985 state = state->next;
13986 xmlFree(tmp);
13987 }
13988}
13989
Daniel Veillard4255d502002-04-16 15:50:10 +000013990/**
13991 * xmlSchemaRegisterAttributes:
13992 * @ctxt: a schema validation context
13993 * @attrs: a list of attributes
13994 *
13995 * Register the list of attributes as the set to be validated on that element
13996 *
13997 * Returns -1 in case of error, 0 otherwise
13998 */
13999static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014000xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
14001{
Daniel Veillard3646d642004-06-02 19:19:14 +000014002 xmlSchemaAttrStatePtr tmp;
14003
14004 ctxt->attr = NULL;
14005 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014006 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014007 if ((attrs->ns != NULL) &&
14008 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
14009 attrs = attrs->next;
14010 continue;
14011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014012 tmp = (xmlSchemaAttrStatePtr)
14013 xmlMalloc(sizeof(xmlSchemaAttrState));
14014 if (tmp == NULL) {
14015 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
14016 return (-1);
14017 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014018 tmp->attr = attrs;
14019 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
14020 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014021 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000014022 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014023 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000014024 else
14025 ctxt->attrTop->next = tmp;
14026 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014027 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014028 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014029 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000014030}
14031
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014032#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000014033/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014034 * xmlSchemaValidateCheckNodeList
14035 * @nodelist: the list of nodes
14036 *
14037 * Check the node list is only made of text nodes and entities pointing
14038 * to text nodes
14039 *
14040 * Returns 1 if true, 0 if false and -1 in case of error
14041 */
14042static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014043xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
14044{
Daniel Veillard4255d502002-04-16 15:50:10 +000014045 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014046 if (nodelist->type == XML_ENTITY_REF_NODE) {
14047 TODO /* implement recursion in the entity content */
14048 }
14049 if ((nodelist->type != XML_TEXT_NODE) &&
14050 (nodelist->type != XML_COMMENT_NODE) &&
14051 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000014052 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014053 return (0);
14054 }
14055 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000014056 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014057 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000014058}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014059#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014060
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014061static void
14062xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
14063{
14064 int i, nbItems;
14065 xmlSchemaTypePtr item, *items;
14066
14067
14068 /*
14069 * During the Assemble of the schema ctxt->curItems has
14070 * been filled with the relevant new items. Fix those up.
14071 */
14072 nbItems = ctxt->assemble->nbItems;
14073 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
14074
14075 for (i = 0; i < nbItems; i++) {
14076 item = items[i];
14077 switch (item->type) {
14078 case XML_SCHEMA_TYPE_ATTRIBUTE:
14079 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
14080 break;
14081 case XML_SCHEMA_TYPE_ELEMENT:
14082 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
14083 NULL, NULL, NULL);
14084 break;
14085 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14086 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
14087 ctxt, NULL);
14088 break;
14089 case XML_SCHEMA_TYPE_GROUP:
14090 xmlSchemaGroupDefFixup(item, ctxt, NULL);
14091 default:
14092 break;
14093 }
14094 }
14095 /*
14096 * Circularity checks.
14097 */
14098 for (i = 0; i < nbItems; i++) {
14099 item = items[i];
14100 switch (item->type) {
14101 case XML_SCHEMA_TYPE_GROUP:
14102 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
14103 break;
14104 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
14105 xmlSchemaCheckAttributeGroupCircular(
14106 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
14107 break;
14108 default:
14109 break;
14110 }
14111 }
14112 /*
14113 * Fixup for all other item.
14114 * TODO: Hmm, not sure if starting from complex/simple types,
14115 * all subsequent items will be reached.
14116 */
14117 for (i = 0; i < nbItems; i++) {
14118 item = items[i];
14119 switch (item->type) {
14120 case XML_SCHEMA_TYPE_SIMPLE:
14121 case XML_SCHEMA_TYPE_COMPLEX:
14122 xmlSchemaTypeFixup(item, ctxt, NULL);
14123 break;
14124 default:
14125 break;
14126 }
14127 }
14128 /*
14129 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014130 * hold by simple type components only (and
14131 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014132 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014133 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014134 for (i = 0; i < nbItems; i++) {
14135 item = items[i];
14136 switch (item->type) {
14137 case XML_SCHEMA_TYPE_SIMPLE:
14138 case XML_SCHEMA_TYPE_COMPLEX:
14139 xmlSchemaCheckDefaults(item, ctxt, NULL);
14140 break;
14141 default:
14142 break;
14143 }
14144 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014145 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014146 /*
14147 * Build the content model for complex types.
14148 */
14149 for (i = 0; i < nbItems; i++) {
14150 item = items[i];
14151 switch (item->type) {
14152 case XML_SCHEMA_TYPE_COMPLEX:
14153 xmlSchemaBuildContentModel(item, ctxt, NULL);
14154 break;
14155 default:
14156 break;
14157 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 }
14159 /*
14160 * Validate value contraint values.
14161 */
14162 for (i = 0; i < nbItems; i++) {
14163 item = items[i];
14164 switch (item->type) {
14165 case XML_SCHEMA_TYPE_ATTRIBUTE:
14166 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
14167 break;
14168 case XML_SCHEMA_TYPE_ELEMENT:
14169 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
14170 break;
14171 default:
14172 break;
14173 }
14174 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014175}
14176
14177/**
14178 * xmlSchemaAssembleByLocation:
14179 * @pctxt: a schema parser context
14180 * @vctxt: a schema validation context
14181 * @schema: the existing schema
14182 * @node: the node that fired the assembling
14183 * @nsName: the namespace name of the new schema
14184 * @location: the location of the schema
14185 *
14186 * Expands an existing schema by an additional schema.
14187 *
14188 * Returns 0 if the new schema is correct, a positive error code
14189 * number otherwise and -1 in case of an internal or API error.
14190 */
14191static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014192xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
14193 xmlSchemaPtr schema,
14194 xmlNodePtr node,
14195 const xmlChar *nsName,
14196 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014197{
14198 const xmlChar *targetNs, *oldtns;
14199 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014200 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014201 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014202 xmlSchemaParserCtxtPtr pctxt;
14203
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014204 /*
14205 * This should be used:
14206 * 1. on <import>(s)
14207 * 2. if requested by the validated instance
14208 * 3. if requested via the API
14209 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014210 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014211 return (-1);
14212 /*
14213 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014214 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014215 if ((vctxt->pctxt == NULL) &&
14216 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
14217 xmlSchemaVErr(vctxt, node,
14218 XML_SCHEMAV_INTERNAL,
14219 "Internal error: xmlSchemaAssembleByLocation, "
14220 "failed to create a temp. parser context.\n",
14221 NULL, NULL);
14222 return (-1);
14223 }
14224 pctxt = vctxt->pctxt;
14225 /*
14226 * Set the counter to produce unique names for anonymous items.
14227 */
14228 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014229 /*
14230 * Acquire the schema document.
14231 */
14232 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
14233 nsName, location, &doc, &targetNs, 0);
14234 if (ret != 0) {
14235 if (doc != NULL)
14236 xmlFreeDoc(doc);
14237 } else if (doc != NULL) {
14238 docElem = xmlDocGetRootElement(doc);
14239 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014240 * Create new assemble info.
14241 */
14242 if (pctxt->assemble == NULL) {
14243 pctxt->assemble = xmlSchemaNewAssemble();
14244 if (pctxt->assemble == NULL) {
14245 xmlSchemaVErrMemory(vctxt,
14246 "Memory error: xmlSchemaAssembleByLocation, "
14247 "allocating assemble info", NULL);
14248 xmlFreeDoc(doc);
14249 return (-1);
14250 }
14251 }
14252 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014253 * Save and reset the context & schema.
14254 */
14255 oldflags = schema->flags;
14256 oldtns = schema->targetNamespace;
14257 olddoc = schema->doc;
14258
14259 xmlSchemaClearSchemaDefaults(schema);
14260 schema->targetNamespace = targetNs;
14261 /* schema->nbCurItems = 0; */
14262 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014263 pctxt->ctxtType = NULL;
14264 pctxt->parentItem = NULL;
14265
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014266 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
14267 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014268 xmlSchemaPostSchemaAssembleFixup(pctxt);
14269 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014270 * Set the counter of items.
14271 */
14272 schema->counter = pctxt->counter;
14273 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014274 * Free the list of assembled components.
14275 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014276 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014277 /*
14278 * Restore the context & schema.
14279 */
14280 schema->flags = oldflags;
14281 schema->targetNamespace = oldtns;
14282 schema->doc = olddoc;
14283 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014284 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014285 return (ret);
14286}
14287
14288/**
14289 * xmlSchemaAssembleByXSIAttr:
14290 * @vctxt: a schema validation context
14291 * @xsiAttr: an xsi attribute
14292 * @noNamespace: whether a schema with no target namespace is exptected
14293 *
14294 * Expands an existing schema by an additional schema using
14295 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
14296 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
14297 * must be set to 1.
14298 *
14299 * Returns 0 if the new schema is correct, a positive error code
14300 * number otherwise and -1 in case of an internal or API error.
14301 */
14302static int
14303xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
14304 xmlAttrPtr xsiAttr,
14305 int noNamespace)
14306{
14307 xmlChar *value;
14308 const xmlChar *cur, *end;
14309 const xmlChar *nsname = NULL, *location;
14310 int count = 0;
14311 int ret = 0;
14312
14313 if (xsiAttr == NULL) {
14314 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
14315 NULL, NULL,
14316 "Internal error: xmlSchemaAssembleByXSIAttr, "
14317 "bad arguments", NULL);
14318 return (-1);
14319 }
14320 /*
14321 * Parse the value; we will assume an even number of values
14322 * to be given (this is how Xerces and XSV work).
14323 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014324 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014325 cur = value;
14326 do {
14327 if (noNamespace != 1) {
14328 /*
14329 * Get the namespace name.
14330 */
14331 while (IS_BLANK_CH(*cur))
14332 cur++;
14333 end = cur;
14334 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14335 end++;
14336 if (end == cur)
14337 break;
14338 count++;
14339 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
14340 cur = end;
14341 }
14342 /*
14343 * Get the URI.
14344 */
14345 while (IS_BLANK_CH(*cur))
14346 cur++;
14347 end = cur;
14348 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14349 end++;
14350 if (end == cur)
14351 break;
14352 count++;
14353 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014354 cur = end;
14355 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014356 xsiAttr->parent, nsname, location);
14357 if (ret == -1) {
14358 xmlSchemaVCustomErr(vctxt,
14359 XML_SCHEMAV_INTERNAL,
14360 (xmlNodePtr) xsiAttr, NULL,
14361 "Internal error: xmlSchemaAssembleByXSIAttr, "
14362 "assembling schemata", NULL);
14363 if (value != NULL)
14364 xmlFree(value);
14365 return (-1);
14366 }
14367 } while (*cur != 0);
14368 if (value != NULL)
14369 xmlFree(value);
14370 return (ret);
14371}
14372
14373/**
14374 * xmlSchemaAssembleByXSIElem:
14375 * @vctxt: a schema validation context
14376 * @elem: an element node possibly holding xsi attributes
14377 * @noNamespace: whether a schema with no target namespace is exptected
14378 *
14379 * Assembles an existing schema by an additional schema using
14380 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
14381 * of the given @elem.
14382 *
14383 * Returns 0 if the new schema is correct, a positive error code
14384 * number otherwise and -1 in case of an internal or API error.
14385 */
14386static int
14387xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
14388 xmlNodePtr elem)
14389{
14390 int ret = 0, retNs = 0;
14391 xmlAttrPtr attr;
14392
14393 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
14394 if (attr != NULL) {
14395 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
14396 if (retNs == -1)
14397 return (-1);
14398 }
14399 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
14400 if (attr != NULL) {
14401 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
14402 if (ret == -1)
14403 return (-1);
14404 }
14405 if (retNs != 0)
14406 return (retNs);
14407 else
14408 return (ret);
14409}
14410
Daniel Veillard4255d502002-04-16 15:50:10 +000014411/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014412 * xmlSchemaValidateCallback:
14413 * @ctxt: a schema validation context
14414 * @name: the name of the element detected (might be NULL)
14415 * @type: the type
14416 *
14417 * A transition has been made in the automata associated to an element
14418 * content model
14419 */
14420static void
14421xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014422 const xmlChar * name ATTRIBUTE_UNUSED,
14423 xmlSchemaTypePtr type, xmlNodePtr node)
14424{
Daniel Veillard4255d502002-04-16 15:50:10 +000014425 xmlSchemaTypePtr oldtype = ctxt->type;
14426 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014427
Daniel Veillard4255d502002-04-16 15:50:10 +000014428#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000014429 xmlGenericError(xmlGenericErrorContext,
14430 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014431 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000014432#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014433 /*
14434 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
14435 */
Daniel Veillard4255d502002-04-16 15:50:10 +000014436 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014437 ctxt->node = node;
14438 ctxt->cur = node->children;
14439 /*
14440 * Assemble new schemata using xsi.
14441 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014442 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014443 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014444
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014445 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
14446 if (ret == -1) {
14447 xmlSchemaVCustomErr(ctxt,
14448 XML_SCHEMAV_INTERNAL,
14449 ctxt->node, NULL,
14450 "Internal error: xmlSchemaValidateElement, "
14451 "assembling schema by xsi", NULL);
14452 return;
14453 }
14454 /*
14455 * NOTE: We won't react on schema parser errors here.
14456 * TODO: But a warning would be nice.
14457 */
14458 }
14459 switch (type->type) {
14460 case XML_SCHEMA_TYPE_ELEMENT: {
14461 /*
14462 * NOTE: The build of the content model
14463 * (xmlSchemaBuildAContentModel) ensures that the element
14464 * declaration (and not a reference to it) will be given.
14465 */
14466 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
14467 /*
14468 * This is paranoid coding ;-)... it should not
14469 * happen here any more.
14470 */
14471 xmlSchemaVCustomErr(ctxt,
14472 XML_SCHEMAV_INTERNAL,
14473 node, NULL,
14474 "Internal error: xmlSchemaValidateCallback, "
14475 "element declaration 'reference' encountered, "
14476 "but an element declaration was expected",
14477 NULL);
14478 return;
14479 }
14480 xmlSchemaValidateElementByDeclaration(ctxt,
14481 (xmlSchemaElementPtr) type);
14482 break;
14483 }
14484 case XML_SCHEMA_TYPE_ANY:
14485 xmlSchemaValidateElementByWildcard(ctxt, type);
14486 break;
14487 default:
14488 break;
14489 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014490 ctxt->type = oldtype;
14491 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014492}
Daniel Veillard4255d502002-04-16 15:50:10 +000014493
Daniel Veillard01fa6152004-06-29 17:04:39 +000014494/**
14495 * xmlSchemaValidateSimpleTypeValue:
14496 * @ctxt: a schema validation context
14497 * @value: the value to be validated
14498 * @fireErrors: shall errors be reported?
14499 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000014500 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014501 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000014502 *
14503 * Validates a value by the given type (user derived or built-in).
14504 *
14505 * Returns 0 if the value is valid, a positive error code
14506 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014507 */
14508static int
14509xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014510 xmlSchemaTypePtr type,
14511 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014512 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014513 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014514 int normalize,
14515 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014516{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014517 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014518 int ret = 0;
14519 xmlChar *normValue = NULL;
14520 int wtsp;
14521
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014522 node = ctxt->node;
14523 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014524 wtsp = ctxt->valueWS;
14525 /*
14526 * Normalize the value.
14527 */
14528 if (normalize &&
14529 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
14530 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
14531
14532 if ((norm != -1) && (norm > ctxt->valueWS)) {
14533 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14534 normValue = xmlSchemaCollapseString(value);
14535 else
14536 normValue = xmlSchemaWhiteSpaceReplace(value);
14537 ctxt->valueWS = norm;
14538 if (normValue != NULL)
14539 value = (const xmlChar *) normValue;
14540 }
14541 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014542 /*
14543 * The nodes of a content must be checked only once,
14544 * this is not working since list types will fire this
14545 * multiple times.
14546 */
14547 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
14548 xmlNodePtr cur = ctxt->cur;
14549
14550 do {
14551 switch (cur->type) {
14552 case XML_TEXT_NODE:
14553 case XML_CDATA_SECTION_NODE:
14554 case XML_PI_NODE:
14555 case XML_COMMENT_NODE:
14556 case XML_XINCLUDE_START:
14557 case XML_XINCLUDE_END:
14558 break;
14559 case XML_ENTITY_REF_NODE:
14560 case XML_ENTITY_NODE:
14561 /* TODO: Scour the entities for illegal nodes. */
14562 TODO break;
14563 case XML_ELEMENT_NODE: {
14564 /* NOTE: Changed to an internal error, since the
14565 * existence of an element node will be already checked in
14566 * xmlSchemaValidateElementBySimpleType and in
14567 * xmlSchemaValidateElementByComplexType.
14568 */
14569 xmlSchemaVCustomErr(ctxt,
14570 XML_SCHEMAV_INTERNAL,
14571 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14572 node, type,
14573 "Element '%s' found in simple type content",
14574 cur->name);
14575 return (XML_SCHEMAV_INTERNAL);
14576 }
14577 case XML_ATTRIBUTE_NODE:
14578 case XML_DOCUMENT_NODE:
14579 case XML_DOCUMENT_TYPE_NODE:
14580 case XML_DOCUMENT_FRAG_NODE:
14581 case XML_NOTATION_NODE:
14582 case XML_HTML_DOCUMENT_NODE:
14583 case XML_DTD_NODE:
14584 case XML_ELEMENT_DECL:
14585 case XML_ATTRIBUTE_DECL:
14586 case XML_ENTITY_DECL:
14587 case XML_NAMESPACE_DECL:
14588#ifdef LIBXML_DOCB_ENABLED
14589 case XML_DOCB_DOCUMENT_NODE:
14590#endif
14591 xmlSchemaVCustomErr(ctxt,
14592 XML_SCHEMAV_INTERNAL,
14593 /* XML_SCHEMAS_ERR_INVALIDELEM, */
14594 node, NULL,
14595 "Node of unexpected type found in simple type content",
14596 NULL);
14597 return (XML_SCHEMAV_INTERNAL);
14598 }
14599 cur = cur->next;
14600 } while (cur != NULL);
14601 }
14602
William M. Brack2f2a6632004-08-20 23:09:47 +000014603 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
14604 xmlSchemaTypePtr base, anyType;
14605
14606 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
14607
14608 base = type->baseType;
14609 while ((base != NULL) &&
14610 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
14611 (base->type != XML_SCHEMA_TYPE_BASIC) &&
14612 (base != anyType)) {
14613 base = base->baseType;
14614 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014615 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014616 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014617 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014618 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14619 "validating complex type '%s'\n",
14620 type->name, NULL);
14621 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14622 /*
14623 * Check facets.
14624 */
14625 /*
14626 * This is somehow not nice, since if an error occurs
14627 * the reported type will be the complex type; the spec
14628 * wants a simple type to be created on the complex type
14629 * if it has a simple content. For now we have to live with
14630 * it.
14631 */
14632 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14633 value, 0, fireErrors);
14634 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014635 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000014636 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14637 "validating facets of complex type '%s'\n",
14638 type->name, NULL);
14639 } else if (ret > 0) {
14640 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000014641 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014642 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000014643 }
14644 }
14645 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014646
14647 if (ctxt->value != NULL) {
14648 xmlSchemaFreeValue(ctxt->value);
14649 ctxt->value = NULL;
14650 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014651 /*
14652 * STREAM-READ-CHILDREN.
14653 */
14654 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014655 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014656 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
14657 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
14658 else
14659 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014660 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014661 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014662 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014663 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014664 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014665 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014666 }
14667 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
14668 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
14669 * a literal in the ·lexical space· of {base type definition}
14670 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014671 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014672 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014673 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014674 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014675 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014676 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014677 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014678 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014679 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014680 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014681 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014682 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014683 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014684 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014685 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14686 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014687 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 facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014691 type->name, NULL);
14692 } else if (ret > 0) {
14693 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014694 /*
14695 Disabled, since the facet validation already reports errors.
14696 if (fireErrors)
14697 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14698 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014699 }
14700 }
14701 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14702
14703 xmlSchemaTypePtr tmpType;
14704 const xmlChar *cur, *end;
14705 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014706 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014707
14708 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
14709 * of white space separated tokens, each of which ·match·es a literal
14710 * in the ·lexical space· of {item type definition}
14711 */
14712
Daniel Veillardc0826a72004-08-10 14:17:33 +000014713 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014714 cur = value;
14715 do {
14716 while (IS_BLANK_CH(*cur))
14717 cur++;
14718 end = cur;
14719 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
14720 end++;
14721 if (end == cur)
14722 break;
14723 tmp = xmlStrndup(cur, end - cur);
14724 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014725 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014726 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014727 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014728 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014729 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14730 "validating an item of list simple type '%s'\n",
14731 type->name, NULL);
14732 break;
14733 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014734 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014735 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014736 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014737 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014738 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 cur = end;
14740 } while (*cur != 0);
14741 /*
14742 * Check facets.
14743 */
14744 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014745 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014746 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014747 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014748 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014749 } else if ((ret == 0) && (applyFacets)) {
14750 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14751 value, len, fireErrors);
14752 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014753 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014754 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14755 "validating facets of list simple type '%s'\n",
14756 type->name, NULL);
14757 } else if (ret > 0) {
14758 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014759 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014760 Disabled, since the facet validation already reports errors.
14761 if (fireErrors)
14762 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014763 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014764 }
14765
Daniel Veillard01fa6152004-06-29 17:04:39 +000014766 }
14767 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14768 xmlSchemaTypeLinkPtr memberLink;
14769
14770 /*
14771 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
14772 * not apply directly; however, the normalization behavior of ·union·
14773 * types is controlled by the value of whiteSpace on that one of the
14774 * ·memberTypes· against which the ·union· is successfully validated.
14775 *
14776 * This means that the value is normalized by the first validating
14777 * member type, then the facets of the union type are applied. This
14778 * needs changing of the value!
14779 */
14780
14781 /*
14782 * 1.2.3 if {variety} is ·union· then the string must ·match· a
14783 * literal in the ·lexical space· of at least one member of
14784 * {member type definitions}
14785 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014786#ifdef DEBUG_UNION_VALIDATION
14787 printf("Union ST : '%s'\n", (const char *) type->name);
14788 printf(" fireErrors : %d\n", fireErrors);
14789 printf(" applyFacets: %d\n", applyFacets);
14790#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014791 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
14792 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014793 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014794 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014795 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014796 type->name, NULL);
14797 ret = -1;
14798 }
14799 if (ret == 0) {
14800 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014801 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
14802 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014803 if ((ret <= 0) || (ret == 0))
14804 break;
14805 memberLink = memberLink->next;
14806 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014807 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014808 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014809 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014810 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014811 type->name, NULL);
14812 } else if (ret > 0) {
14813 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014814 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014815 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014816 }
14817 }
14818 /*
14819 * Apply facets (pattern, enumeration).
14820 */
14821 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
14822 int mws;
14823 /*
14824 * The normalization behavior of ·union· types is controlled by
14825 * the value of whiteSpace on that one of the ·memberTypes·
14826 * against which the ·union· is successfully validated.
14827 */
14828 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014829 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014830 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14831 "the value was already normalized for the union simple "
14832 "type '%s'.\n", type->name, NULL);
14833 }
14834 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
14835 if (mws > ctxt->valueWS) {
14836 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
14837 normValue = xmlSchemaCollapseString(value);
14838 else
14839 normValue = xmlSchemaWhiteSpaceReplace(value);
14840 if (normValue != NULL)
14841 value = (const xmlChar *) normValue;
14842 }
14843
14844 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
14845 value, 0, fireErrors);
14846 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014848 "Internal error: xmlSchemaValidateSimpleTypeValue, "
14849 "validating facets of union simple type '%s'\n",
14850 type->name, NULL);
14851 } else if (ret > 0) {
14852 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
14853 /*
14854 if (fireErrors)
14855 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
14856 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014857 }
14858 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014859 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014860 ctxt->valueWS = wtsp;
14861 if (normValue != NULL)
14862 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014863 return (ret);
14864}
14865
14866/**
14867 * xmlSchemaValidateSimpleTypeElement:
14868 * @ctxt: a schema validation context
14869 * @node: the element node to be validated.
14870 *
14871 * Validate the element against a simple type.
14872 *
14873 * Returns 0 if the element is valid, a positive error code
14874 * number otherwise and -1 in case of an internal or API error.
14875 */
14876static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014877xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014878 xmlSchemaTypePtr type,
14879 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014880{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014881 xmlSchemaTypePtr oldtype;
14882 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014883 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014884 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014885 int ret = 0, retval = 0;
14886
Daniel Veillard01fa6152004-06-29 17:04:39 +000014887 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014888 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
14889 "Internal error: xmlSchemaValidateElementBySimpleType, "
14890 "bad arguments", NULL);
14891 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014892 }
14893
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014894 oldtype = ctxt->type;
14895 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014896 /*
14897 * cvc-type: 3.1.2 The element information item must have no element
14898 * information item [children].
14899 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014900 /*
14901 * STREAM: Child nodes are processed.
14902 */
14903 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014904 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014905 /*
14906 * TODO: Entities, will they produce elements as well?
14907 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014908 if (cur->type == XML_ELEMENT_NODE) {
14909 xmlSchemaVCustomErr(ctxt,
14910 XML_SCHEMAV_CVC_TYPE_3_1_2,
14911 node, type,
14912 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014913 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014914 }
14915 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014916 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014917
Daniel Veillard01fa6152004-06-29 17:04:39 +000014918 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014919 * cvc-type 3.1.1:
14920 *
14921 * The attributes of must be empty, excepting those whose namespace name
14922 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
14923 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014924 */
14925 /*
14926 * STREAM: Attribute nodes are processed.
14927 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014928 attr = node->properties;
14929 while (attr != NULL) {
14930 if ((attr->ns == NULL) ||
14931 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
14932 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
14933 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
14934 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
14935 (!xmlStrEqual
14936 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014937 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014938 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
14939 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014940 }
14941 attr = attr->next;
14942 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014943 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014944 * This will skip validation if the type is 'anySimpleType' and
14945 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014946 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014947 if ((valSimpleContent == 1) &&
14948 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
14949 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014950 xmlChar *value;
14951
14952 value = xmlNodeGetContent(node);
14953 /*
14954 * NOTE: This call will not check the content nodes, since
14955 * this should be checked here already.
14956 */
14957 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14958 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014959 if (value != NULL)
14960 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014961 if (retval != 0)
14962 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000014963 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014964 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014965 return (ret);
14966}
Daniel Veillard4255d502002-04-16 15:50:10 +000014967
14968/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014969 * xmlSchemaValQNameAcquire:
14970 * @value: the lexical represantation of the QName value
14971 * @node: the node to search for the corresponding namespace declaration
14972 * @nsName: the resulting namespace name if found
14973 *
14974 * Checks that a value conforms to the lexical space of the type QName;
14975 * if valid, the corresponding namespace name is searched and retured
14976 * as a copy in @nsName. The local name is returned in @localName as
14977 * a copy.
14978 *
14979 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
14980 * namespace declaration was found in scope; -1 in case of an internal or
14981 * API error.
14982 */
14983static int
14984xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
14985 xmlChar **nsName, xmlChar **localName)
14986{
14987 int ret;
14988 xmlChar *local = NULL;
14989
14990 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
14991 return (-1);
14992 *nsName = NULL;
14993 *localName = NULL;
14994 ret = xmlValidateQName(value, 1);
14995 if (ret == 0) {
14996 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014997 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014998
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014999 /*
15000 * NOTE: xmlSplitQName2 will return a duplicated
15001 * string.
15002 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015003 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015004 if (local == NULL)
15005 local = xmlStrdup(value);
15006 ns = xmlSearchNs(node->doc, node, prefix);
15007 /*
15008 * A namespace need not to be found if the prefix is NULL.
15009 */
15010 if (ns != NULL) {
15011 /*
15012 * TODO: Is it necessary to duplicate the URI here?
15013 */
15014 *nsName = xmlStrdup(ns->href);
15015 } else if (prefix != NULL) {
15016 xmlFree(prefix);
15017 if (local != NULL)
15018 xmlFree(local);
15019 return (2);
15020 }
15021 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015022 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015023 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015024 } else
15025 return (1);
15026 return (ret);
15027}
15028
15029/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015030 * xmlSchemaHasElemContent:
15031 * @node: the node
15032 *
15033 * Scours the content of the given node for element
15034 * nodes.
15035 *
15036 * Returns 1 if an element node is found,
15037 * 0 otherwise.
15038 */
15039static int
15040xmlSchemaHasElemContent(xmlNodePtr node)
15041{
15042 if (node == NULL)
15043 return (0);
15044 node = node->children;
15045 while (node != NULL) {
15046 if (node->type == XML_ELEMENT_NODE)
15047 return (1);
15048 node = node->next;
15049 }
15050 return (0);
15051}
15052/**
15053 * xmlSchemaHasElemOrCharContent:
15054 * @node: the node
15055 *
15056 * Scours the content of the given node for element
15057 * and character nodes.
15058 *
15059 * Returns 1 if an element or character node is found,
15060 * 0 otherwise.
15061 */
15062static int
15063xmlSchemaHasElemOrCharContent(xmlNodePtr node)
15064{
15065 if (node == NULL)
15066 return (0);
15067 node = node->children;
15068 while (node != NULL) {
15069 switch (node->type) {
15070 case XML_ELEMENT_NODE:
15071 /*
15072 * TODO: Ask Daniel if these are all character nodes.
15073 */
15074 case XML_TEXT_NODE:
15075 case XML_CDATA_SECTION_NODE:
15076 /*
15077 * TODO: How XML_ENTITY_NODEs evaluated?
15078 */
15079 case XML_ENTITY_REF_NODE:
15080 case XML_ENTITY_NODE:
15081 return (1);
15082 break;
15083 default:
15084 break;
15085 }
15086 node = node->next;
15087 }
15088 return (0);
15089}
15090
15091
15092/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015093 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000015094 * @ctxt: a schema validation context
15095 * @node: the top node.
15096 *
15097 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015098 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000015099 *
15100 * Returns 0 if the element is schemas valid, a positive error code
15101 * number otherwise and -1 in case of internal or API error.
15102 */
15103static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015104xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
15105 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015106{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015107 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015108 int ret = 0;
15109 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015110 xmlAttrPtr attr;
15111 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015112 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000015113
15114 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015115 * This one is called by xmlSchemaValidateElementByWildcardInternal,
15116 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015117 * Note that @elemDecl will be the declaration and never the
15118 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015119 */
Daniel Veillard3646d642004-06-02 19:19:14 +000015120
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015121 if (ctxt == NULL) {
15122 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
15123 "Internal error: xmlSchemaValidateElementByDeclaration, "
15124 "bad arguments.\n",
15125 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015126 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015127 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015128
15129 elem = ctxt->node;
15130
15131 /*
15132 * cvc-elt (3.3.4) : 1
15133 */
15134 if (elemDecl == NULL) {
15135 xmlSchemaVCustomErr(ctxt,
15136 XML_SCHEMAV_CVC_ELT_1,
15137 elem, NULL,
15138 "No matching declaration available", NULL);
15139 return (ctxt->err);
15140 }
15141 /*
15142 * cvc-elt (3.3.4) : 2
15143 */
15144 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
15145 xmlSchemaVCustomErr(ctxt,
15146 XML_SCHEMAV_CVC_ELT_2,
15147 elem, NULL,
15148 "The element declaration is abstract", NULL);
15149 return (ctxt->err);
15150 }
15151
15152 /*
15153 * cvc-elt (3.3.4) : 3
15154 * Handle 'xsi:nil'.
15155 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015156
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015157 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015158 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015159 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15160 ctxt->node = (xmlNodePtr) attr;
15161 ctxt->cur = attr->children;
15162 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
15163 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
15164 BAD_CAST attrValue, 1, 1, 1, 1);
15165 ctxt->node = elem;
15166 ctxt->type = (xmlSchemaTypePtr) elemDecl;
15167 if (ret < 0) {
15168 xmlSchemaVCustomErr(ctxt,
15169 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015170 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015171 "Internal error: xmlSchemaValidateElementByDeclaration, "
15172 "validating the attribute 'xsi:nil'", NULL);
15173 if (attrValue != NULL)
15174 xmlFree(attrValue);
15175 return (-1);
15176 }
15177 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015178 /*
15179 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015180 */
15181 xmlSchemaVCustomErr(ctxt,
15182 XML_SCHEMAV_CVC_ELT_3_1,
15183 elem, NULL,
15184 "The element is not 'nillable'", NULL);
15185 } else {
15186 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015187 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015188 ret = 0;
15189 /*
15190 * cvc-elt (3.3.4) : 3.2.1
15191 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015192 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15193 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015194 xmlSchemaVCustomErr(ctxt,
15195 XML_SCHEMAV_CVC_ELT_3_2_1,
15196 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015197 elem, (xmlSchemaTypePtr) elemDecl,
15198 "The 'nilled' element must have no character or "
15199 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015200 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
15201 }
15202 /*
15203 * cvc-elt (3.3.4) : 3.2.2
15204 */
15205 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
15206 (elemDecl->value != NULL)) {
15207 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
15208 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015209 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015210 "There is a fixed value constraint defined for "
15211 "the 'nilled' element", NULL);
15212 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
15213 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015214 if (ret == 0)
15215 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015216 }
15217 }
15218 if (attrValue != NULL)
15219 xmlFree(attrValue);
15220 }
15221
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015222
15223 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015224 /*
15225 * cvc-elt (3.3.4) : 4
15226 * Handle 'xsi:type'.
15227 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015228
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015229 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
15230 if (attr != NULL) {
15231 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015232
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015233 /*
15234 * TODO: We should report a *warning* that the type was overriden
15235 * by the instance.
15236 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015237
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015238 /*
15239 * cvc-elt (3.3.4) : 4.1
15240 */
15241 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
15242 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
15243 &nsName, &local);
15244 if (ret < 0) {
15245 xmlSchemaVCustomErr(ctxt,
15246 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015247 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015248 "Internal error: xmlSchemaValidateElementByDeclaration, "
15249 "validating the attribute 'xsi:type'", NULL);;
15250 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015251 FREE_AND_NULL(nsName)
15252 FREE_AND_NULL(local)
15253 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015254 } else if (ret == 1) {
15255 xmlSchemaVSimpleTypeErr(ctxt,
15256 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15257 (xmlNodePtr) attr, attrValue,
15258 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
15259 } else if (ret == 2) {
15260 xmlSchemaVCustomErr(ctxt,
15261 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
15262 (xmlNodePtr) attr,
15263 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15264 "The QName value '%s' has no "
15265 "corresponding namespace declaration in scope",
15266 attrValue);
15267 } else {
15268 /*
15269 * cvc-elt (3.3.4) : 4.2
15270 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015271 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
15272 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015273 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015274
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015275 xmlSchemaVCustomErr(ctxt,
15276 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015277 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015278 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
15279 "The value %s does not resolve to a type "
15280 "definition",
15281 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
15282 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015283 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015284 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015285 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015286 */
15287 }
15288 }
15289 FREE_AND_NULL(attrValue)
15290 FREE_AND_NULL(nsName)
15291 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015292 }
15293 /* TODO: Change the handling of missing types according to
15294 * the spec.
15295 */
15296 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015297 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015298 XML_SCHEMAV_CVC_TYPE_1,
15299 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015300 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015301 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015302 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015303
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015304 /*
15305 * TODO: Since this should be already checked by the content model automaton,
15306 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
15307 * has been changed to XML_SCHEMAV_INTERNAL.
15308 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015309 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000015310 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015311 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015312 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015313 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015314 "Element %s: missing child %s\n",
15315 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015316 }
15317 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015318 }
15319 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015320 /*
15321 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015322 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015323 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015324 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015325 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015326 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015327 "Element %s: missing child %s found %s\n",
15328 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015329 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015330 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015331 */
15332 if (elemHasContent == -1)
15333 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
15334 /*
15335 * cvc-elt (3.3.4) : 5
15336 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015337 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015338 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015339 * cvc-elt (3.3.4) : 5.1
15340 * If the declaration has a {value constraint},
15341 * the item has neither element nor character [children] and
15342 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015343 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015344 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
15345 /*
15346 * cvc-elt (3.3.4) : 5.1.1
15347 * If the ·actual type definition· is a ·local type definition·
15348 * then the canonical lexical representation of the {value constraint}
15349 * value must be a valid default for the ·actual type definition· as
15350 * defined in Element Default Valid (Immediate) (§3.3.6).
15351 */
15352 /*
15353 * NOTE: 'local' above means types aquired by xsi:type.
15354 */
15355 ret = 0;
15356 if (actualType != elemDecl->subtypes) {
15357 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
15358 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
15359 elemDecl->value, NULL);
15360 if (ret < 0) {
15361 xmlSchemaVCustomErr(ctxt,
15362 XML_SCHEMAV_INTERNAL,
15363 elem, actualType,
15364 "Internal error: xmlSchemaValidateElementByDeclaration, "
15365 "validating a default value", NULL);
15366 return (-1);
15367 }
15368 }
15369 /*
15370 * cvc-elt (3.3.4) : 5.1.2
15371 * The element information item with the canonical lexical
15372 * representation of the {value constraint} value used as its
15373 * ·normalized value· must be ·valid· with respect to the
15374 * ·actual type definition· as defined by Element Locally Valid (Type)
15375 * (§3.3.4).
15376 */
15377 /*
15378 * Disable validation of the simple content, since it was already
15379 * done above.
15380 */
15381 if (ret == 0) {
15382 if (actualType != elemDecl->subtypes)
15383 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15384 else
15385 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
15386 ctxt->node = elem;
15387 if (ret < 0) {
15388 xmlSchemaVCustomErr(ctxt,
15389 XML_SCHEMAV_INTERNAL,
15390 elem, actualType,
15391 "Internal error: xmlSchemaValidateElementByDeclaration, "
15392 "validating against the type", NULL);
15393 return (-1);
15394 }
15395 /*
15396 * PSVI: Create a text node on the instance element.
15397 */
15398 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
15399 xmlNodePtr textChild;
15400
15401 textChild = xmlNewText(elemDecl->value);
15402 if (textChild == NULL) {
15403 xmlSchemaVCustomErr(ctxt,
15404 XML_SCHEMAV_INTERNAL,
15405 elem, actualType,
15406 "Internal error: xmlSchemaValidateElementByDeclaration, "
15407 "could not create a default text node for the instance",
15408 NULL);
15409 } else
15410 xmlAddChild(elem, textChild);
15411 }
15412 }
15413
15414 } else {
15415 /*
15416 * 5.2.1 The element information item must be ·valid· with respect
15417 * to the ·actual type definition· as defined by Element Locally
15418 * Valid (Type) (§3.3.4).
15419 */
15420 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
15421 ctxt->node = elem;
15422 if (ret < 0) {
15423 xmlSchemaVCustomErr(ctxt,
15424 XML_SCHEMAV_INTERNAL,
15425 elem, actualType,
15426 "Internal error: xmlSchemaValidateElementByDeclaration, "
15427 "validating a default value", NULL);
15428 return (-1);
15429 }
15430 /*
15431 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
15432 * not applied, all of the following must be true:
15433 */
15434
15435 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
15436 /*
15437 * 5.2.2.1 The element information item must have no element
15438 * information item [children].
15439 *
15440 * TODO REDUNDANT: If the actual type exists, the above call to
15441 * xmlSchemaValidateElementByType will already check for element
15442 * nodes.
15443 */
15444 if (xmlSchemaHasElemContent(elem)) {
15445 xmlSchemaVCustomErr(ctxt,
15446 XML_SCHEMAV_CVC_ELT_5_2_2_1,
15447 elem, (xmlSchemaTypePtr) elemDecl,
15448 "Elements in the content are not allowed if it is "
15449 "constrained by a fixed value", NULL);
15450 } else {
15451 /*
15452 * 5.2.2.2 The appropriate case among the following must
15453 * be true:
15454 */
15455
15456 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
15457 xmlChar *value;
15458 /*
15459 * 5.2.2.2.1 If the {content type} of the ·actual type
15460 * definition· is mixed, then the *initial value* of the
15461 * item must match the canonical lexical representation
15462 * of the {value constraint} value.
15463 *
15464 * ... the *initial value* of an element information
15465 * item is the string composed of, in order, the
15466 * [character code] of each character information item in
15467 * the [children] of that element information item.
15468 */
15469 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15470 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15471 /*
15472 * TODO: Report invalid & expected values as well.
15473 * TODO: Implement the cononical stuff.
15474 */
15475 xmlSchemaVCustomErr(ctxt,
15476 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
15477 elem, (xmlSchemaTypePtr) elemDecl,
15478 "The value does not match the cononical "
15479 "lexical representation of the fixed constraint",
15480 NULL);
15481 }
15482 if (value != NULL)
15483 xmlFree(value);
15484 } else if ((actualType->contentType ==
15485 XML_SCHEMA_CONTENT_SIMPLE) ||
15486 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15487 xmlChar *value;
15488
15489 /*
15490 * 5.2.2.2.2 If the {content type} of the ·actual type
15491 * definition· is a simple type definition, then the
15492 * *actual value* of the item must match the canonical
15493 * lexical representation of the {value constraint} value.
15494 */
15495 /*
15496 * TODO: *actual value* is the normalized value, impl. this.
15497 * TODO: Report invalid & expected values as well.
15498 * TODO: Implement the cononical stuff.
15499 *
15500 */
15501 value = xmlNodeListGetString(elem->doc, elem->children, 1);
15502 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
15503 xmlSchemaVCustomErr(ctxt,
15504 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
15505 elem, (xmlSchemaTypePtr) elemDecl,
15506 "The normalized value does not match the cononical "
15507 "lexical representation of the fixed constraint",
15508 NULL);
15509 }
15510 if (value != NULL)
15511 xmlFree(value);
15512
15513 }
15514 /*
15515 * TODO: What if the content type is not 'mixed' or simple?
15516 */
15517
15518 }
15519
15520 }
15521 }
15522
15523 /*
15524 * TODO: 6 The element information item must be ·valid· with respect to each of
15525 * the {identity-constraint definitions} as per Identity-constraint
15526 * Satisfied (§3.11.4).
15527 */
15528
15529 /*
15530 * TODO: 7 If the element information item is the ·validation root·, it must be
15531 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
15532 */
15533
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015534 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000015535}
15536
Daniel Veillard4255d502002-04-16 15:50:10 +000015537/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015538 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015539 * @ctxt: a schema validation context
15540 * @node: the top node.
15541 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015542 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
15543 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015544 *
15545 * Returns 0 if the element is valid, a positive error code
15546 * number otherwise and -1 in case of an internal error.
15547 */
15548static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015549xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
15550 xmlSchemaWildcardPtr wild,
15551 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015552{
15553 const xmlChar *uri;
15554 int ret = 0;
15555 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015556
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015557 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015558 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15559 if (ret == -1) {
15560 xmlSchemaVCustomErr(ctxt,
15561 XML_SCHEMAV_INTERNAL,
15562 ctxt->node, NULL,
15563 "Internal error: xmlSchemaValidateElement, "
15564 "assembling schema by xsi", NULL);
15565 return (-1);
15566 }
15567 /*
15568 * NOTE: We won't react on schema parser errors here.
15569 * TODO: But a warning would be nice.
15570 */
15571 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015572 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
15573 xmlSchemaElementPtr decl = NULL;
15574
15575 if (node->ns != NULL)
15576 decl = xmlHashLookup3(ctxt->schema->elemDecl,
15577 node->name, node->ns->href, NULL);
15578 else
15579 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name, NULL, NULL);
15580 if (decl != NULL) {
15581 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015582 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015583 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015584 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015585 "Internal error: xmlSchemaValidateAnyInternal, "
15586 "validating an element in the context of a wildcard.",
15587 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000015588 }
15589 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015590 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
15591 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015592 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015593 node, wild, "No matching global declaration available");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015594 return (ctxt->err);
15595 }
15596 }
15597 if (node->children != NULL) {
15598 child = node->children;
15599 do {
15600 if (child->type == XML_ELEMENT_NODE) {
15601 if (child->ns != NULL)
15602 uri = child->ns->href;
15603 else
15604 uri = NULL;
15605 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015606 /* TODO: error code. */
15607 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015608 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015609 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000015610 return (ctxt->err);
15611 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015612 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
15613 wild, child);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015614 if (ret != 0)
15615 return (ret);
15616 }
15617 child = child->next;
15618 } while (child != NULL);
15619 }
15620 return (0);
15621}
15622
15623/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015624 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000015625 * @ctxt: a schema validation context
15626 *
15627 * Returns 0 if the element is valid, a positive error code
15628 * number otherwise and -1 in case of an internal or API error.
15629 */
15630static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015631xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
15632 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015633{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015634 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
15635 (ctxt->node == NULL)) {
15636 xmlSchemaVCustomErr(ctxt,
15637 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
15638 "Internal error: xmlSchemaValidateElementByWildcard, "
15639 "bad arguments", NULL);
15640 return (-1);
15641 }
15642 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
15643 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000015644}
15645
15646/**
William M. Brack2f2a6632004-08-20 23:09:47 +000015647 * xmlSchemaValidateAnyTypeContent:
15648 * @ctxt: a schema validation context
15649 * @node: the current element
15650 *
15651 * This one validates the content of an element of the type
15652 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
15653 * thus elements in the subtree will be validated, if a corresponding
15654 * declaration in the schema exists.
15655 *
15656 * Returns 0 if the element and its subtree is valid, a positive error code
15657 * otherwise and -1 in case of an internal or API error.
15658 */
15659static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015660xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
15661 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000015662{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015663 xmlSchemaTypePtr oldtype;
15664 xmlNodePtr top, cur;
15665 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000015666 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015667
15668 if ((type == NULL) || (ctxt->node == NULL))
15669 return (-1);
15670
15671 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015672 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015673
15674 oldtype = ctxt->type;
15675 top = ctxt->node;
15676 /*
15677 * STREAM: Child nodes are processed.
15678 */
15679 cur = ctxt->node->children;
15680 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015681 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015682 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015683 /*
15684 * The process contents of the wildcard is "lax", thus
15685 * we need to validate the element if a declaration
15686 * exists.
15687 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015688 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000015689 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015690 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015691 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015692 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015693 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015694 ctxt->node = cur;
15695 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
15696 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000015697 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015698 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015699 "Internal error: xmlSchemaValidateAnyTypeContent, "
15700 "validating an element in the context of a wildcard.",
15701 NULL, NULL);
15702 return (ret);
15703 } else if (ret > 0)
15704 return (ret);
15705 skipContent = 1;
15706 }
15707 }
15708 /*
15709 * Browse the full subtree, deep first.
15710 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015711 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015712 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015713 cur = cur->children;
15714 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015715 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015716 cur = cur->next;
15717 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015718 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015719 while (cur != top) {
15720 if (cur->parent != NULL)
15721 cur = cur->parent;
15722 if ((cur != top) && (cur->next != NULL)) {
15723 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000015724 break;
15725 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015726 if (cur->parent == NULL) {
15727 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015728 break;
15729 }
15730 }
15731 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015732 if (cur == top)
15733 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000015734 } else
15735 break;
15736 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015737 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000015738 return (0);
15739}
15740
15741/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015742 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000015743 * @ctxt: a schema validation context
15744 * @node: the top node.
15745 *
15746 * Validate the content of an element expected to be a complex type type
15747 * xmlschema-1.html#cvc-complex-type
15748 * Validation Rule: Element Locally Valid (Complex Type)
15749 *
15750 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000015751 * number otherwise and -1 in case of internal or API error.
15752 * Note on reported errors: Although it might be nice to report
15753 * the name of the simple/complex type, used to validate the content
15754 * of a node, it is quite unnecessary: for global defined types
15755 * the local name of the element is equal to the NCName of the type,
15756 * for local defined types it makes no sense to output the internal
15757 * computed name of the type. TODO: Instead, one should attach the
15758 * struct of the type involved to the error handler - this allows
15759 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000015760 */
15761static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015762xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015763 xmlSchemaTypePtr type,
15764 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015765{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015766 xmlSchemaTypePtr oldtype;
15767 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015768 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000015769 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015770 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015771
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015772 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
15773 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015774
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015775 oldtype = ctxt->type;
15776 ctxt->type = type;
15777 elem = ctxt->node;
15778
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015779 /*
15780 * Verify the attributes
15781 */
15782 /*
15783 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015784 */
15785 /* NOTE: removed, since a check for abstract is
15786 * done in the cvc-type constraint.
15787 *
15788 *
15789 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
15790 * xmlSchemaVComplexTypeErr(ctxt,
15791 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
15792 * elem, type,
15793 * "The type definition is abstract");
15794 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
15795 *}
15796 */
15797
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015798 attrs = ctxt->attr;
15799 attrTop = ctxt->attrTop;
15800 /*
15801 * STREAM: Attribute nodes are processed.
15802 */
15803 xmlSchemaRegisterAttributes(ctxt, elem->properties);
15804 xmlSchemaValidateAttributes(ctxt, elem, type);
15805 if (ctxt->attr != NULL)
15806 xmlSchemaFreeAttributeStates(ctxt->attr);
15807 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015808 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015809
15810 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015811 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015812 * model was defined. Somehow ->contModel is always not NULL
15813 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015814 * TODO: Check if the obove still occurs.
15815 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015816 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015817 case XML_SCHEMA_CONTENT_EMPTY: {
15818 /*
15819 * 1 If the {content type} is empty, then the element information
15820 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000015821 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015822 /*
15823 * TODO: Is the entity stuff correct?
15824 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015825 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015826 xmlSchemaVComplexTypeErr(ctxt,
15827 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015828 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015829 "Character or element content is not allowed, "
15830 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015831 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015832 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015833 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015834 case XML_SCHEMA_CONTENT_MIXED:
15835 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015836 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015837 /*
15838 * The type has 'anyType' as its base and no content model
15839 * is defined -> use 'anyType' as the type to validate
15840 * against.
15841 */
15842 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
15843 /* TODO: Handle -1. */
15844 break;
15845 }
15846 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015847 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015848 {
15849 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015850
15851 /*
15852 * Content model check initialization.
15853 */
15854 if (type->contModel != NULL) {
15855 oldregexp = ctxt->regexp;
15856 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
15857 (xmlRegExecCallbacks)
15858 xmlSchemaValidateCallback, ctxt);
15859#ifdef DEBUG_AUTOMATA
15860 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
15861#endif
15862 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015863 /*
15864 * STREAM: Children are processed.
15865 */
15866 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015867 while (child != NULL) {
15868 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015869 if (child->ns != NULL)
15870 nsUri = child->ns->href;
15871 else
15872 nsUri = NULL;
15873 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015874 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015875 /*
15876 * URGENT TODO: Could we anchor an error report
15877 * here to notify of invalid elements?
15878 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015879#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000015880 if (ret < 0)
15881 xmlGenericError(xmlGenericErrorContext,
15882 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000015883 else
15884 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015885 " --> %s\n", child->name);
15886#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015887 if (ret < 0) {
15888 xmlSchemaVComplexTypeErr(ctxt,
15889 XML_SCHEMAV_ELEMENT_CONTENT,
15890 child, NULL/* type */,
15891 "This element is not expected");
15892 ret = 1;
15893 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015894 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
15895 /*
15896 * TODO: Ask Daniel if this are all character nodes.
15897 */
15898 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
15899 (child->type == XML_ENTITY_NODE) ||
15900 (child->type == XML_ENTITY_REF_NODE) ||
15901 (child->type == XML_CDATA_SECTION_NODE))) {
15902 /*
15903 * 2.3 If the {content type} is element-only, then the
15904 * element information item has no character information
15905 * item [children] other than those whose [character
15906 * code] is defined as a white space in [XML 1.0 (Second
15907 * Edition)].
15908 */
William M. Brack2f2a6632004-08-20 23:09:47 +000015909 xmlSchemaVComplexTypeErr(ctxt,
15910 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015911 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000015912 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015913 "because the content type is element-only");
15914 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015915 break;
15916 }
15917 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015918 }
15919 /*
15920 * Content model check finalization.
15921 */
15922 if (type->contModel != NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015923 if (ret != 1) {
15924 ret = xmlRegExecPushString(ctxt->regexp, NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015925#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015926 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015927 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015928#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000015929 if (ret == 0) {
15930 /* TODO: Hmm, can this one really happen? */
15931 xmlSchemaVComplexTypeErr(ctxt,
15932 XML_SCHEMAV_ELEMENT_CONTENT,
15933 elem, type, "Missing child element(s)");
15934 } else if (ret < 0) {
15935 xmlSchemaVComplexTypeErr(ctxt,
15936 XML_SCHEMAV_ELEMENT_CONTENT,
15937 elem, type, "Missing child element(s)");
15938#ifdef DEBUG_CONTENT
15939 } else {
15940 xmlGenericError(xmlGenericErrorContext,
15941 "Element %s content check succeeded\n",
15942 elem->name);
15943
15944#endif
15945 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015946 }
15947 xmlRegFreeExecCtxt(ctxt->regexp);
15948 ctxt->regexp = oldregexp;
15949 }
15950 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015951 break;
15952 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015953 case XML_SCHEMA_CONTENT_BASIC:
15954 /*
15955 * If the simple content was already validated
15956 * (e.g. a default value), the content need not
15957 * to be validated again.
15958 */
15959 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015960 xmlChar *value = NULL;
15961 /*
15962 * We hit a complexType with a simpleContent resolving
15963 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000015964 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015965 /*
15966 * 2.2 If the {content type} is a simple type definition,
15967 * then the element information item has no element
15968 * information item [children], and the ·normalized value·
15969 * of the element information item is ·valid· with respect
15970 * to that simple type definition as defined by String
15971 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015972 */
15973 /*
15974 * STREAM: Children are processed.
15975 */
15976 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015977 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015978 /*
15979 * TODO: Could the entity stuff produce elements
15980 * as well?
15981 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982 if (child->type == XML_ELEMENT_NODE) {
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 "Element content is not allowed, because "
15987 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000015988 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
15989 break;
15990 }
15991 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015992 }
15993 ctxt->node = elem;
15994 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015995 if (ret == 0) {
15996 /*
15997 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000015998 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015999 /*
16000 * STREAM: Children are processed.
16001 */
16002 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016003 value = NULL;
16004 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016005 value = xmlNodeGetContent(elem);
16006 /*
16007 * URGENT TODO: Should facets for the simple type validation be
16008 * disabled, if the derivation of facets for complex types
16009 * is implemented?
16010 */
16011 /*
16012 * NOTE: This call won't check the correct types of the
16013 * content nodes, since this should be done here.
16014 */
16015 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016016 if (ret > 0) {
16017 /*
16018 * NOTE: Although an error will be reported by
16019 * xmlSchemaValidateSimpleTypeValue, the spec wants
16020 * a specific complex type error to be reported
16021 * additionally.
16022 */
16023 xmlSchemaVComplexTypeErr(ctxt,
16024 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016025 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016026 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016027 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16028 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016029 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016030 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016031 "Element '%s': Error while validating character "
16032 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016033 elem->name, type->name);
16034 if (value != NULL)
16035 xmlFree(value);
16036 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016037 return (-1);
16038 }
William M. Brack2f2a6632004-08-20 23:09:47 +000016039 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016040 if (ret == 0) {
16041 /*
16042 * Apply facets of the complexType. Be sure to pass the
16043 * built-in type to xmlSchemaValidateFacetsInternal.
16044 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000016046 * are used, or if the facets, defined by this complex type,
16047 * are to be used only. This here applies both facet sets.
16048 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016049
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016050 ret = xmlSchemaValidateFacetsInternal(ctxt,
16051 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016052 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000016053 xmlSchemaVComplexTypeErr(ctxt,
16054 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016055 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016056 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000016057 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
16058 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016059 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016060 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016061 "Element '%s': Error while validating character "
16062 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000016063 "apply facets.\n",
16064 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016065 if (value != NULL)
16066 xmlFree(value);
16067 ctxt->type = oldtype;
16068 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016069 }
16070 }
16071 if (value != NULL)
16072 xmlFree(value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016073
Daniel Veillard01fa6152004-06-29 17:04:39 +000016074 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016075 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016076 default:
16077 TODO xmlGenericError(xmlGenericErrorContext,
16078 "unimplemented content type %d\n",
16079 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000016080 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016081 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016082 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016083}
16084
16085/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016086 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000016087 * @ctxt: a schema validation context
16088 * @elem: an element
16089 * @type: the list of type declarations
16090 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016091 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000016092 *
16093 * Returns 0 if the element is schemas valid, a positive error code
16094 * number otherwise and -1 in case of internal or API error.
16095 */
16096static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016097xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016098 xmlSchemaTypePtr type,
16099 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016100{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016101 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000016102
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016103
16104 if ((ctxt == NULL) || (type == NULL)) {
16105 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16106 "Internal error: xmlSchemaValidateElementByType, "
16107 "bad arguments", NULL);
16108 return (-1);
16109 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016110 /*
16111 * This one is called by "xmlSchemaValidateElementByDeclaration".
16112 * It will forward to the proper validation
16113 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016114 */
16115 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016116 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016117 XML_SCHEMAV_CVC_TYPE_1,
16118 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016119 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016120 return (XML_SCHEMAV_CVC_TYPE_1);
16121 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016123 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016124 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016125 XML_SCHEMAV_CVC_TYPE_2,
16126 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000016127 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016128 return (XML_SCHEMAV_CVC_TYPE_2);
16129 }
16130
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016131 switch (type->type) {
16132 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016133 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
16134 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016135 break;
16136 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016137 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16138 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016139 break;
16140 case XML_SCHEMA_TYPE_BASIC:
16141 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
16142 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
16143 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016144 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
16145 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016146 break;
16147 default:
16148 ret = -1;
16149 break;
16150 }
16151 if (ret == -1)
16152 return (-1);
16153 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016154 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016155}
16156
16157
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016158static int
16159xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
16160 xmlSchemaAttributePtr decl,
16161 xmlSchemaAttrStatePtr state,
16162 xmlAttrPtr attr)
16163{
16164 xmlChar *value;
16165 const xmlChar *defValue;
16166 xmlSchemaValPtr defVal;
16167 int fixed;
16168 int ret;
16169
16170 if (decl->subtypes == NULL) {
16171 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
16172 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
16173 }
16174 value = xmlNodeListGetString(attr->doc, attr->children, 1);
16175 ctxt->node = (xmlNodePtr) attr;
16176 ctxt->cur = attr->children;
16177 /*
16178 * NOTE: This call also checks the content nodes for correct type.
16179 */
16180 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
16181 value, 1, 1, 1, 1);
16182
16183 /*
16184 * Handle 'fixed' attributes.
16185 */
16186 if (ret > 0) {
16187 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
16188 /*
16189 * NOTE: Fixed value constraints will be not
16190 * applied if the value was invalid, because:
16191 * 1. The validation process does not return a precomputed
16192 * value.
16193 * 2. An invalid value implies a violation of a fixed
16194 * value constraint.
16195 */
16196 } else if (ret == 0) {
16197 state->state = XML_SCHEMAS_ATTR_CHECKED;
16198 if (xmlSchemaGetEffectiveValueConstraint(decl,
16199 &fixed, &defValue, &defVal) && (fixed == 1)) {
16200 /*
16201 * cvc-au : Attribute Locally Valid (Use)
16202 * For an attribute information item to be·valid·
16203 * with respect to an attribute use its ·normalized
16204 * value· must match the canonical lexical representation
16205 * of the attribute use's {value constraint} value, if it
16206 * is present and fixed.
16207 */
16208 /*
16209 * NOTE: the validation context holds in ctxt->value the
16210 * precomputed value of the attribute; well for some types,
16211 * fallback to string comparison if no computed value
16212 * exists.
16213 */
16214 if (((ctxt->value != NULL) &&
16215 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
16216 ((ctxt->value == NULL) &&
16217 (! xmlStrEqual(defValue, BAD_CAST value)))) {
16218 state->state =
16219 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
16220 }
16221 }
16222 }
16223 if (value != NULL) {
16224 xmlFree(value);
16225 }
16226 return (ret);
16227}
16228
Daniel Veillard4255d502002-04-16 15:50:10 +000016229/**
16230 * xmlSchemaValidateAttributes:
16231 * @ctxt: a schema validation context
16232 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000016233 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000016234 *
16235 * Validate the attributes of an element.
16236 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000016237 * 1. Existent, invalid attributes are reported in the form
16238 * "prefix:localName".
16239 * Reason: readability - it is easier to find the actual XML
16240 * representation of the attributes QName.
16241 * 2. Missing attributes are reported in the form
16242 * {"URI", "localName"}.
16243 * This is necessary, since the the prefix need not to be declared
16244 * at all, and thus is not computable.
16245 *
Daniel Veillard4255d502002-04-16 15:50:10 +000016246 * Returns 0 if the element is schemas valid, a positive error code
16247 * number otherwise and -1 in case of internal or API error.
16248 */
16249static int
Daniel Veillard3646d642004-06-02 19:19:14 +000016250xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016251{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016252 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000016253 int ret;
16254 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016255 const xmlChar *defValue;
16256 xmlSchemaValPtr defVal;
16257 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016258 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000016259 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016260 int found;
William M. Brack803812b2004-06-03 02:11:24 +000016261 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016262 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016263 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000016264#ifdef DEBUG_ATTR_VALIDATION
16265 int redundant = 0;
16266#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016267
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016268
Daniel Veillardc0826a72004-08-10 14:17:33 +000016269 /*
16270 * Allow all attributes if the type is anyType.
16271 */
16272 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
16273 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016274
16275 oldnode = ctxt->node;
16276 if (type != NULL)
16277 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000016278 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000016279 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000016280 attrDecl = attrUse->attr;
16281#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016282 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000016283 printf("attr use - use: %d\n", attrDecl->occurs);
16284#endif
16285 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
16286
16287 if (curState->decl == attrUse->attr) {
16288#ifdef DEBUG_ATTR_VALIDATION
16289 redundant = 1;
16290#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016291 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016292 attr = curState->attr;
16293#ifdef DEBUG_ATTR_VALIDATION
16294 printf("attr - name: %s\n", attr->name);
16295 if (attr->ns != NULL)
16296 printf("attr - ns: %s\n", attr->ns->href);
16297 else
16298 printf("attr - ns: none\n");
16299#endif
16300 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016301 if (attr == NULL)
16302 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016303 if (attrDecl->ref != NULL) {
16304 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016305 continue;
16306 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016307 if ((attrDecl->refNs == NULL) ||
16308 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016309 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016310 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016311 continue;
16312 }
16313 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016314 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016315 continue;
16316 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016317 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016318 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016319 if (attr->ns == NULL) {
16320 /*
William M. Bracke7091952004-05-11 15:09:58 +000016321 * accept an unqualified attribute only if the target
16322 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016323 */
Daniel Veillard3646d642004-06-02 19:19:14 +000016324 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000016325 /*
16326 * This check was removed, since the target namespace
16327 * was evaluated during parsing and already took
16328 * "attributeFormDefault" into account.
16329 */
16330 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016331 continue;
16332 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000016333 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016334 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000016335 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000016336 attr->ns->href))
16337 continue;
16338 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016339 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016340#ifdef DEBUG_ATTR_VALIDATION
16341 printf("found\n");
16342#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016343 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000016344 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016345 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000016346 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016347 if (!found) {
16348 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
16349 xmlSchemaAttrStatePtr tmp;
16350
Daniel Veillard3646d642004-06-02 19:19:14 +000016351#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016352 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016353#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016354 /*
16355 * Add a new dummy attribute state.
16356 */
16357 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
16358 if (tmp == NULL) {
16359 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
16360 ctxt->node = oldnode;
16361 return (-1);
16362 }
16363 tmp->attr = NULL;
16364 tmp->state = XML_SCHEMAS_ATTR_MISSING;
16365 tmp->decl = attrDecl;
16366 tmp->next = NULL;
16367
16368 if (reqAttrStates == NULL) {
16369 reqAttrStates = tmp;
16370 reqAttrStatesTop = tmp;
16371 } else {
16372 reqAttrStatesTop->next = tmp;
16373 reqAttrStatesTop = tmp;
16374 }
16375 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
16376 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
16377 &fixed, &defValue, &defVal))) {
16378 xmlSchemaAttrStatePtr tmp;
16379 /*
16380 * Handle non existent default/fixed attributes.
16381 */
16382 tmp = (xmlSchemaAttrStatePtr)
16383 xmlMalloc(sizeof(xmlSchemaAttrState));
16384 if (tmp == NULL) {
16385 xmlSchemaVErrMemory(ctxt,
16386 "registering schema specified attributes", NULL);
16387 ctxt->node = oldnode;
16388 return (-1);
16389 }
16390 tmp->attr = NULL;
16391 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
16392 tmp->decl = attrDecl;
16393 tmp->value = defValue;
16394 tmp->next = NULL;
16395
16396 if (defAttrStates == NULL) {
16397 defAttrStates = tmp;
16398 defAttrStates = tmp;
16399 } else {
16400 defAttrStates->next = tmp;
16401 defAttrStatesTop = tmp;
16402 }
16403 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016404 }
16405 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000016406 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016407 /*
16408 * Add required attributes to the attribute states of the context.
16409 */
16410 if (reqAttrStates != NULL) {
16411 if (ctxt->attr == NULL) {
16412 ctxt->attr = reqAttrStates;
16413 } else {
16414 ctxt->attrTop->next = reqAttrStates;
16415 }
16416 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016417 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016418 /*
16419 * Process wildcards.
16420 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016421
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016422 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000016423#ifdef DEBUG_ATTR_VALIDATION
16424 xmlSchemaWildcardNsPtr ns;
16425 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016426 if (type->attributeWildcard->processContents ==
16427 XML_SCHEMAS_ANY_LAX)
16428 printf("processContents: lax\n");
16429 else if (type->attributeWildcard->processContents ==
16430 XML_SCHEMAS_ANY_STRICT)
16431 printf("processContents: strict\n");
16432 else
16433 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000016434 if (type->attributeWildcard->any)
16435 printf("type: any\n");
16436 else if (type->attributeWildcard->negNsSet != NULL) {
16437 printf("type: negated\n");
16438 if (type->attributeWildcard->negNsSet->value == NULL)
16439 printf("ns: (absent)\n");
16440 else
16441 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
16442 } else if (type->attributeWildcard->nsSet != NULL) {
16443 printf("type: set\n");
16444 ns = type->attributeWildcard->nsSet;
16445 while (ns != NULL) {
16446 if (ns->value == NULL)
16447 printf("ns: (absent)\n");
16448 else
16449 printf("ns: %s\n", ns->value);
16450 ns = ns->next;
16451 }
16452 } else
16453 printf("empty\n");
16454
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016455
16456#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000016457 curState = ctxt->attr;
16458 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016459 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
16460 if (curState->attr->ns != NULL)
16461 nsURI = curState->attr->ns->href;
16462 else
16463 nsURI = NULL;
16464 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
16465 nsURI)) {
16466 /*
16467 * Handle processContents.
16468 */
16469 if ((type->attributeWildcard->processContents ==
16470 XML_SCHEMAS_ANY_LAX) ||
16471 (type->attributeWildcard->processContents ==
16472 XML_SCHEMAS_ANY_STRICT)) {
16473
16474 attr = curState->attr;
16475 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016476 attr->name, nsURI);
16477 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016478 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016479 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016480 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016481 } else if (type->attributeWildcard->processContents ==
16482 XML_SCHEMAS_ANY_LAX) {
16483 curState->state = XML_SCHEMAS_ATTR_CHECKED;
16484 }
16485 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000016486 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000016487 }
16488 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016489 curState = curState->next;
16490 }
16491 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016492
Daniel Veillardc0826a72004-08-10 14:17:33 +000016493 /*
16494 * Report missing and illegal attributes.
16495 */
16496 if (ctxt->attr != NULL) {
16497 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016498 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016499 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
16500 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016501 if (curState->decl != NULL) {
16502 if (curState->decl->ref != NULL)
16503 attrDecl = curState->decl->refDecl;
16504 else
16505 attrDecl = curState->decl;
16506 } else
16507 attrDecl = NULL;
16508 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
16509 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
16510 } else if (curState->state ==
16511 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
16512 xmlSchemaVCustomErr(ctxt,
16513 XML_SCHEMAV_CVC_ATTRIBUTE_2,
16514 (xmlNodePtr) attr,
16515 (xmlSchemaTypePtr) attrDecl,
16516 "The type definition is absent",
16517 NULL);
16518 } else if (curState->state ==
16519 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
16520 xmlSchemaVCustomErr(ctxt,
16521 XML_SCHEMAV_CVC_AU,
16522 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
16523 "The value does not match the fixed value "
16524 "constraint", NULL);
16525 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016526 /* TODO: "prohibited" won't ever be touched here!.
16527 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
16528 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016529 /*
16530 * TODO: One might report different error messages
16531 * for the following errors.
16532 */
16533 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016534 xmlSchemaVIllegalAttrErr(ctxt,
16535 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
16536 } else {
16537 xmlSchemaVIllegalAttrErr(ctxt,
16538 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
16539 }
16540 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016541 }
16542 curState = curState->next;
16543 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016544 }
16545
16546 /*
16547 * Add missing default/fixed attributes.
16548 */
16549 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
16550 curState = defAttrStates;
16551 while (curState != NULL) {
16552 attrDecl = curState->decl;
16553 if (attrDecl->ref != NULL)
16554 attrDecl = attrDecl->refDecl;
16555 /*
16556 * PSVI: Add a new attribute node to the current element.
16557 */
16558 if (attrDecl->targetNamespace == NULL) {
16559 xmlNewProp(elem, attrDecl->name, curState->value);
16560 } else {
16561 xmlNsPtr ns;
16562
16563 ns = xmlSearchNsByHref(elem->doc, elem,
16564 attrDecl->targetNamespace);
16565 if (ns == NULL) {
16566 xmlChar prefix[12];
16567 int counter = 1;
16568
16569 attr = curState->attr;
16570 /*
16571 * Create a namespace declaration on the validation
16572 * root node if no namespace declaration is in scope.
16573 */
16574 snprintf((char *) prefix, sizeof(prefix), "p");
16575 /*
16576 * This is somehow not performant, since the ancestor
16577 * axis beyond @elem will be searched as well.
16578 */
16579 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
16580 while (ns != NULL) {
16581 if (counter > 1000) {
16582 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
16583 XML_SCHEMAV_INTERNAL,
16584 "Internal error: xmlSchemaValidateAttributes, "
16585 "could not compute a ns prefix for "
16586 "default/fixed attribute '%s'.\n",
16587 attrDecl->name, NULL);
16588
16589 break;
16590 }
16591 snprintf((char *) prefix,
16592 sizeof(prefix), "p%d", counter++);
16593 ns = xmlSearchNs(elem->doc, elem,
16594 BAD_CAST prefix);
16595 }
16596 if (ns == NULL) {
16597 ns = xmlNewNs(ctxt->validationRoot,
16598 attrDecl->targetNamespace, BAD_CAST prefix);
16599 xmlNewNsProp(elem, ns, attrDecl->name,
16600 curState->value);
16601 }
16602 } else {
16603 xmlNewNsProp(elem, ns, attrDecl->name,
16604 curState->value);
16605 }
16606 }
16607 curState = curState->next;
16608 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016609 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016610 if (defAttrStates != NULL)
16611 xmlSchemaFreeAttributeStates(defAttrStates);
16612
Daniel Veillard3646d642004-06-02 19:19:14 +000016613#ifdef DEBUG_ATTR_VALIDATION
16614 if (redundant)
16615 xmlGenericError(xmlGenericErrorContext,
16616 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
16617 type->name);
16618#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016619 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016620 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016621}
16622
16623/**
16624 * xmlSchemaValidateElement:
16625 * @ctxt: a schema validation context
16626 * @elem: an element
16627 *
16628 * Validate an element in a tree
16629 *
16630 * Returns 0 if the element is schemas valid, a positive error code
16631 * number otherwise and -1 in case of internal or API error.
16632 */
16633static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016634xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016635{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016636 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016637 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016638
Daniel Veillardc0826a72004-08-10 14:17:33 +000016639 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016640 * This one is called by xmlSchemaValidateDocument and
16641 * xmlSchemaValidateOneElement.
16642 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016643 if (ctxt->schema == NULL) {
16644 /*
16645 * No schema was specified at time of creation of the validation
16646 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
16647 * of the instance to build a schema.
16648 */
16649 if (ctxt->pctxt == NULL)
16650 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
16651 if (ctxt->pctxt == NULL)
16652 return (-1);
16653 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
16654 if (ctxt->schema == NULL)
16655 return (-1);
16656 /* TODO: assign user data. */
16657 ctxt->pctxt->error = ctxt->error;
16658 ctxt->pctxt->warning = ctxt->warning;
16659 ctxt->xsiAssemble = 1;
16660 } else
16661 ctxt->xsiAssemble = 0;
16662 /* ctxt->options |= XML_SCHEMA_VAL_VC_I_CREATE;
16663 * ctxt->xsiAssemble = 1;
16664 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016665 /*
16666 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016667 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016668 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016669 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16670 if (ret == -1) {
16671 xmlSchemaVCustomErr(ctxt,
16672 XML_SCHEMAV_INTERNAL,
16673 ctxt->node, NULL,
16674 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016675 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016676 }
16677 /*
16678 * NOTE: We won't react on schema parser errors here.
16679 * TODO: But a warning would be nice.
16680 */
16681 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016682 if (ret != -1) {
16683 if (ctxt->node->ns != NULL)
16684 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
16685 ctxt->node->ns->href);
16686 else
16687 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
16688
16689 if (elemDecl == NULL) {
16690 xmlSchemaVCustomErr(ctxt,
16691 XML_SCHEMAV_CVC_ELT_1,
16692 ctxt->node, NULL,
16693 "No matching global declaration available", NULL);
16694 ret = XML_SCHEMAV_CVC_ELT_1;
16695 } else {
16696 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
16697 if (ret < 0) {
16698 xmlSchemaVCustomErr(ctxt,
16699 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
16700 "Internal error: xmlSchemaValidateElement, "
16701 "calling validation by declaration", NULL);
16702 }
16703 }
16704 }
16705 /* ctxt->xsiAssemble = 0; */
16706 if (ctxt->xsiAssemble) {
16707 if (ctxt->schema != NULL) {
16708 xmlSchemaFree(ctxt->schema);
16709 ctxt->schema = NULL;
16710 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016711 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016712 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016713}
16714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016715
Daniel Veillard4255d502002-04-16 15:50:10 +000016716/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016717 * xmlSchemaValidateOneElement:
16718 * @ctxt: a schema validation context
16719 * @elem: an element node
16720 *
16721 * Validate a branch of a tree, starting with the given @elem.
16722 *
16723 * Returns 0 if the element and its subtree is valid, a positive error
16724 * code number otherwise and -1 in case of an internal or API error.
16725 */
16726int
16727xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
16728{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016729 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016730 return (-1);
16731
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016732 if (ctxt->schema == NULL) {
16733 xmlSchemaVErr(ctxt, NULL,
16734 XML_SCHEMAV_INTERNAL,
16735 "API error: xmlSchemaValidateOneElement, "
16736 "no schema specified.\n", NULL, NULL);
16737 return (-1);
16738 }
16739
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016740 ctxt->doc = elem->doc;
16741 ctxt->err = 0;
16742 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016743 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016744 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016745 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000016746}
16747
16748/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016749 * xmlSchemaValidateDocument:
16750 * @ctxt: a schema validation context
16751 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016752 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000016753 *
16754 * Validate a document tree in memory.
16755 *
16756 * Returns 0 if the document is schemas valid, a positive error code
16757 * number otherwise and -1 in case of internal or API error.
16758 */
16759static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016760xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16761{
Daniel Veillard4255d502002-04-16 15:50:10 +000016762 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016763
Daniel Veillard4255d502002-04-16 15:50:10 +000016764 root = xmlDocGetRootElement(doc);
16765 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016766 xmlSchemaVCustomErr(ctxt,
16767 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
16768 (xmlNodePtr) doc, NULL,
16769 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016770 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016771 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016772 /* ctxt->options |= XML_SCHEMA_VAL_XSI_ASSEMBLE; */
Daniel Veillard4255d502002-04-16 15:50:10 +000016773 /*
16774 * Okay, start the recursive validation
16775 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016776 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016777 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016778 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016779
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016780 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000016781}
16782
16783/************************************************************************
16784 * *
16785 * SAX Validation code *
16786 * *
16787 ************************************************************************/
16788
16789/************************************************************************
16790 * *
16791 * Validation interfaces *
16792 * *
16793 ************************************************************************/
16794
16795/**
16796 * xmlSchemaNewValidCtxt:
16797 * @schema: a precompiled XML Schemas
16798 *
16799 * Create an XML Schemas validation context based on the given schema
16800 *
16801 * Returns the validation context or NULL in case of error
16802 */
16803xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016804xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
16805{
Daniel Veillard4255d502002-04-16 15:50:10 +000016806 xmlSchemaValidCtxtPtr ret;
16807
16808 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
16809 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016810 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016811 return (NULL);
16812 }
16813 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000016814 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000016815 ret->attrTop = NULL;
16816 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000016817 return (ret);
16818}
16819
16820/**
16821 * xmlSchemaFreeValidCtxt:
16822 * @ctxt: the schema validation context
16823 *
16824 * Free the resources associated to the schema validation context
16825 */
16826void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016827xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
16828{
Daniel Veillard4255d502002-04-16 15:50:10 +000016829 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016830 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016831 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016832 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000016833 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016834 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016835 if (ctxt->pctxt != NULL) {
16836 xmlSchemaFreeParserCtxt(ctxt->pctxt);
16837 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016838 xmlFree(ctxt);
16839}
16840
16841/**
16842 * xmlSchemaSetValidErrors:
16843 * @ctxt: a schema validation context
16844 * @err: the error function
16845 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000016846 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000016847 *
William M. Brack2f2a6632004-08-20 23:09:47 +000016848 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000016849 */
16850void
16851xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016852 xmlSchemaValidityErrorFunc err,
16853 xmlSchemaValidityWarningFunc warn, void *ctx)
16854{
Daniel Veillard4255d502002-04-16 15:50:10 +000016855 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016856 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016857 ctxt->error = err;
16858 ctxt->warning = warn;
16859 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016860 if (ctxt->pctxt != NULL)
16861 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000016862}
16863
16864/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016865 * xmlSchemaGetValidErrors:
16866 * @ctxt: a XML-Schema validation context
16867 * @err: the error function result
16868 * @warn: the warning function result
16869 * @ctx: the functions context result
16870 *
16871 * Get the error and warning callback informations
16872 *
16873 * Returns -1 in case of error and 0 otherwise
16874 */
16875int
16876xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
16877 xmlSchemaValidityErrorFunc * err,
16878 xmlSchemaValidityWarningFunc * warn, void **ctx)
16879{
16880 if (ctxt == NULL)
16881 return (-1);
16882 if (err != NULL)
16883 *err = ctxt->error;
16884 if (warn != NULL)
16885 *warn = ctxt->warning;
16886 if (ctx != NULL)
16887 *ctx = ctxt->userData;
16888 return (0);
16889}
16890
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016891
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016892/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016893 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016894 * @ctxt: a schema validation context
16895 * @options: a combination of xmlSchemaValidOption
16896 *
16897 * Sets the options to be used during the validation.
16898 *
16899 * Returns 0 in case of success, -1 in case of an
16900 * API error.
16901 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016902int
16903xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
16904 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016905
16906{
16907 int i;
16908
16909 if (ctxt == NULL)
16910 return (-1);
16911 /*
16912 * WARNING: Change the start value if adding to the
16913 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016914 * TODO: Is there an other, more easy to maintain,
16915 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016916 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016917 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016918 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016919 xmlSchemaVErr(ctxt, NULL,
16920 XML_SCHEMAV_INTERNAL,
16921 "Internal error: xmlSchemaSetValidOptions, "
16922 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016923 return (-1);
16924 }
16925 }
16926 ctxt->options = options;
16927 return (0);
16928}
16929
16930/**
Daniel Veillard6927b102004-10-27 17:29:04 +000016931 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016932 * @ctxt: a schema validation context
16933 *
William M. Brack21e4ef22005-01-02 09:53:13 +000016934 * Get the validation context options.
16935 *
16936 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016937 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016938int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016939xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
16940
16941{
16942 if (ctxt == NULL)
16943 return (-1);
16944 else
16945 return (ctxt->options);
16946}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016947
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016948
Daniel Veillard259f0df2004-08-18 09:13:18 +000016949/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016950 * xmlSchemaValidateDoc:
16951 * @ctxt: a schema validation context
16952 * @doc: a parsed document tree
16953 *
16954 * Validate a document tree in memory.
16955 *
16956 * Returns 0 if the document is schemas valid, a positive error code
16957 * number otherwise and -1 in case of internal or API error.
16958 */
16959int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016960xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
16961{
Daniel Veillard4255d502002-04-16 15:50:10 +000016962 int ret;
16963
16964 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016965 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000016966
16967 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000016968 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016969 ctxt->nberrors = 0;
16970
16971 /*
16972 if (ctxt->schema == NULL) {
16973 xmlSchemaVErr(ctxt, NULL,
16974 XML_SCHEMAV_INTERNAL,
16975 "API error: xmlSchemaValidateDoc, "
16976 "no schema specified and assembling of schemata "
16977 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
16978 "is not enabled.\n", NULL, NULL);
16979 return (-1);
16980 }
16981 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016982 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016983 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000016984}
16985
16986/**
16987 * xmlSchemaValidateStream:
16988 * @ctxt: a schema validation context
16989 * @input: the input to use for reading the data
16990 * @enc: an optional encoding information
16991 * @sax: a SAX handler for the resulting events
16992 * @user_data: the context to provide to the SAX handler.
16993 *
16994 * Validate a document tree in memory.
16995 *
16996 * Returns 0 if the document is schemas valid, a positive error code
16997 * number otherwise and -1 in case of internal or API error.
16998 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016999int
Daniel Veillard4255d502002-04-16 15:50:10 +000017000xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017001 xmlParserInputBufferPtr input, xmlCharEncoding enc,
17002 xmlSAXHandlerPtr sax, void *user_data)
17003{
Daniel Veillard4255d502002-04-16 15:50:10 +000017004 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017005 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017006 ctxt->input = input;
17007 ctxt->enc = enc;
17008 ctxt->sax = sax;
17009 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017010 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017011}
17012
17013#endif /* LIBXML_SCHEMAS_ENABLED */